Home » Php » php – Calling methods on object gets 'call to member function on array' error

php – Calling methods on object gets 'call to member function on array' error

Posted by: admin February 25, 2020 Leave a comment

Questions:

I inherited this project from my predecessor, and he was way overqualified. A lot of stuff he wrote goes over my head. But as far as vanilla php goes, I’m pretty confident, and can’t for the life of me figure out why the application thinks the object I created is an array. Maybe I don’t actually know anything. You tell me.

use via\zoom\Bulletin;
use via\zoom\DatabaseConnection;
require_once('includes/config.php');
require_once(CORE .'sql.php');
require_once(CORE . 'model.php');
require_once(CORE . 'bulletin.php');

// If we've passed the validation step we can guarantee we have a valid $active_user
validate();

//run if a page deletion has been requested

if (isset($_GET['delpage'])) {

$del = $_GET['delpage'];

$bulletin = new Bulletin;
$bulletin = Bulletin::get($del);

if(!empty($bulletin))
{
    $bulletin->delete();
    /*
        So.
        For some reason, the above object is cast as an array.
        If you try to cast it as an object, it defaults to stdClass.

        On the left we have a method complaining that it can't work outside of its class. Hard stop, array to method exception.

        On the right we have an object with all the right data, but set to the wrong class, so it can't find the delete method at all. Hard stop, undefined method exception.
     */
    //this is the workaround, pulled the script straight from the delete method in the model class
    /*$dbh = DatabaseConnection::get();

    $query_string = "DELETE FROM brochure_generator_bulletin WHERE id = $del";

    try {
        $dbh->query($query_string);
        //return true;
    } catch (\Exception $e) {
        //return false;
    }*/

}

header('Location: bulletins');
exit();
}

Here’s the get method from the Bulletin class, extends Model–

public static function get( ...$ids )
    {    
        $matches = parent::get( ...$ids );    
        foreach( $matches as &$match )
        {    
            $match->content = json_decode( $match->content );    
        }    
        return $matches;     
    }

And here’s the delete method from the Model Class:

public function delete()
    {
        if (isset($this->id)) {
            $dbh = DatabaseConnection::get();

            $query_string = "DELETE FROM {$this->table_name} WHERE id = \"{$this->id}\"";

            try {
                $dbh->query($query_string);
                return true;
            } catch (\Exception $e) {
                return false;
            }
        }    
        return false;
    }

What am I missing? Is he using a framework I’m not familiar with? I’m utterly grasping at straws here, and at this point my options are grab all the method scripts and stick them where they need to be inline, or just starting over from the ground up.

How to&Answers:

You don’t need to create a new Bulletin object before using the static get() method, so you can remove this:

$bulletin = new Bulletin;

That $bulletin variable is immediately overwritten by the next line anyway.

$bulletin = Bulletin::get($del);

get() takes one or more ids and returns an array of one or more corresponding objects. You’re giving it one id and expecting one object back, but it’s still going to return that object inside an array. You just need to get the object out of the array so you can call its delete method.

if(!empty($bulletin))
{
    $bulletin = reset($bulletin); // get the first item in the array
    $bulletin->delete();

You could also review the model and see if it has a different method that returns a single object rather than an array of objects.