0

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?

yivi
  • 42,438
  • 18
  • 116
  • 138
Peon
  • 7,902
  • 7
  • 59
  • 100
  • http://php.net/manual/en/language.oop5.static.php Just using (misusing in your case) `$self` doesn't make `fetch` static. – Alex Blex Oct 25 '17 at 11:39
  • 3
    "User" is not a special type of "database". Also, by making an SQL wrapper, you actually make you code less secure. Also, use of static code should be avoided, since it causes tight coupling to be introduced. You probably should look up what [data mapper](https://martinfowler.com/eaaCatalog/dataMapper.html) is ... ya know, to not embarress the university . – tereško Oct 25 '17 at 12:04
  • 4
    A user *is not* a database. – Jimbo Oct 25 '17 at 12:15
  • While his class organization may be arguably wrong, the class is actually called `Users`, not user; so it represents at the very least a collection of users, not a specific user instance. And that's besides the point anyway; since it can represent whatever the OP wants, that's a matter of opinion and debate; there is hardly **one** school of thought on class naming and resource naming. – yivi Oct 25 '17 at 12:19
  • 1
    @yivi that makes it actually even worse. – tereško Oct 25 '17 at 12:19

2 Answers2

1

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.

yivi
  • 42,438
  • 18
  • 116
  • 138
1

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).

sevavietl
  • 3,762
  • 1
  • 14
  • 21