I have this empty array:
$newRow = [];
I need somehow push this object into $newRow
:
$newRow = $this->db->table(self::TABLE_NAME)->where(array('status' => $status));
But if I do it this way, it always overwrite an array. Methods like array_merge
or:
$newRow = (object)array_push((array)$newRow,(array)$this->db->table(self::TABLE_NAME)->where(array('status' => $status));
Are useless because it always sends me an error Call to undefined method stdClass::fetchAll()
.
Full code if you need:
public function filter($showActiveOnly, $showNotAdded, showHalfAdded, $showDeclined)
{
$newRow = [];
$statuses = [
'dodano' => $showActiveOnly,
'nedodano' => $showNotAdded,
'casdodano' => $showHalfAdded,
'storno' => $showDeclined,
];
foreach ($statuses as $status => $addFilter) {
if ($addFilter) {
$newRow = $this->db->table(self::TABLE_NAME)->where(array('status' => $status));
}
}
return $newRow ?: $this->db->table(self::TABLE_NAME);
}
This is a func where fetchAll is
public function getFiltered($showActiveOnly, $showNotAdded, $showHalfAdded, $showDeclined)
{
return $this->filter($showActiveOnly, $showNotAdded, $showHalfAdded, $showDeclined)->fetchAll();
}
CodePudding user response:
Your code does have several issues. I will now try to explain to you what improvements you can make to your code to avoid errors during execution.
It 's all about return types
The first big issue in your code are return types. Your filter
function returns either an array or the result of the fetchAll
method, which can be either an array or something completely different. Your error message suggests that there may also be stdClass objects as a result here. Different return types are always a mess. You should avoid that.
The following example is shortened and demonstrates the power of type hints. Type hints can avoid errors like you 're experiencing right now.
<?php
declare(strict_types=1);
namespace Marcel;
use Exception;
use PDO;
class Example
{
protected PDO $database;
public function __construct(PDO $pdo)
{
$this->database = $pdo;
}
protected function filter(string $param1, string $param2, string $param3): array
{
// result container for database rowsets
$result = [];
// some logic here that selects data from the database and pushes it
// into the result container
try {
$sql = "SELECT blah FROM blubb WHERE yadda = :param";
$stmt = $this->database->prepare($sql);
$stmt->bindParam('param', $param1);
$stmt->execute();
foreach ($stmt->fetchAll(PDO::FETCH_DEFAULT) as $row) {
$result[] = $row;
}
} catch (Exception $e) {
// error handling - so important
}
// the result array and nothing else will be returned
return $result;
}
public function getFiltered(string $param1, string $param2, string $param3): array
{
return $this->filter($param1, $param2, $param3);
}
}
Have you noticed what happend here? The filter
method returns only arrays. The fetchAll
database method will be executed in the filter
method only. The return type will not be messed up. It 's just an array of database rowsets.
If you want to return two different things a possible solution could look like the following example. But trust me, this is ugly a f.
protected function filter(string $param1, string $param2, string $param3): PDOStatement|array
{
$result = [];
$stmt = ...; // instance of PDOStatement with fetchAll method
...
return $result ?: $stmt;
}
public function getFiltered(string $param1, string $param2, string $param3): array
{
$result = $this->filter(string $param1, string $param2, string $param3);
return ($result instanceof PDOStatement)
? $result->fetchAll(PDO::FETCH_DEFAULT)
: $result;
}
Kids! Do not try the above shown at home!
Collections with PHP
The above shown example class stores the found rowsets in an $result
array. That 's fine so far. Depending on how many resultsets you want to store in that array, this can be very slow and consuming a hell of memory. A better solution are collections like ArrayObject or SplObjectStorage.
$row = [
'id' => 1,
'name' => 'blah',
];
$collection = new ArrayObject();
$collection->append($row);
The advantages: Optimized memory consumption on iteration because of internal use of yielding and iterators and an object orientated interface.
Conclusion
Your code ends up in error messages, because your filter
function returns different things like arrays or objects. Your getFiltered
method awaits an object, that has a fetchAll
method, although your filter
method returns an array or somewhat completely different, that does not have a fetchAll
method.
If you want to use a method on the result of another method, just make sure that exactly this one object is returned, or check the return value to see if it is indeed the expected object.
Just keep things simple and stupid and don 't try to overinvent something simple, e.g. because you think method chaining looks cool or something even more senseless. Check your return values!
CodePudding user response:
Well, you're not really adding, you are currently overwriting.
<?php
class AddToArray
{
public function filter($showActiveOnly, $showNotAdded, $showHalfAdded, $showDeclined)
{
$newRow = [];
$statuses = [
'dodano' => $showActiveOnly,
'nedodano' => $showNotAdded,
'casdodano' => $showHalfAdded,
'storno' => $showDeclined,
];
foreach ($statuses as $status => $addFilter)
{
if ($addFilter)
{
$newRow[] = $this->db->table(self::TABLE_NAME)->where(array('status' => $status));
// or :
// array_push($newRow, $this->db->table(self::TABLE_NAME)->where(array('status' => $status)));
}
}
return $newRow ? : $this->db->table(self::TABLE_NAME);
}
}
That should do the trick.
Either use the short hand method: $array[] = ''
or the dedicated function, array_push($array, $NewEntry)
.
You're not using fetchAll()
correctly, which is out of the scope of the original question.
Here is the documentation of fetchAll()
:
https://www.php.net/manual/en/pdostatement.fetchall.php
For you, you should probably call it like this:
$rows = $this->db->table(self::TABLE_NAME)->where(array('status' => $status));
$rows->execute();
$results = $rows->fetchAll();