Use static parent instance with extended instance values

92 Views Asked by At

I have a main class

abstract class Database
{
    protected $table;

    public function where(array $params)
    {
        // ...
    }

    public function get()
    {
        // ...
    }
}

and then I use extended versions of the class:

Users extends Database
{
    protected $table = 'users';
}

Now, whenever I need to select users, I just use:

$db = new Users();
$results = $db->where(['id' => 1])->get();

This works fine, but I decided that it would be nice, to make a static shortcut specifically for requests by id, but I'm having problems initializing the class statistically. I created a method fetch, that should set the Id and make the return with the found object.

class Database // Had to drop abstract, since self cant be used
{
    protected $table;

    public static function fetch(int $id)
    {
        $self = new self;
        $result = $self->where(['id' => $id])->get();

        return $result;
    }
}

But, as I commented, self cant be used in abstract, so I had to drop it and it creates a new instance without the table value, since it's empty in the parent class.

Any ideas how to make this work?

2

There are 2 best solutions below

0
sevavietl On BEST ANSWER

Use static instead of self in the method:

public static function fetch(int $id)
{
    $self = new static;
    $result = $self->where(['id' => $id])->get();

    return $result;
}

This way you will get the instance of an extended class (e.g. Users), but not the one in which method is declared (i.e. Database).

0
yivi On

You are trying to resolve at run-time the class. self won't help you. You need to use static for that. Read on late static bindings.

class Database // Had to drop abstract, since self cant be used
{
    protected $table;

    public static function fetch(int $id)
    {
        $self = new static;
        $result = $self->where(['id' => $id])->get();

        return $result;
    }
}

Since you were using self, on runtime you'd get the original base class (the class where self is actually used). By using static, you get the class where the code is actually run.