Home > Enterprise >  How to push objects in php?
How to push objects in php?

Time:07-15

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();
  •  Tags:  
  • php
  • Related