Kończymy nasz model – tym razem metodą find, która zwraca model z odpowiednio ustawionymi polami ID oraz data, jeżeli taki w bazie danych znajdzie. Do dzieła!

Troszkę poprawimy konstruktor:

abstract class Model {
    
    public $id;
    private $data = array();
    protected static $conn;
    const OPERATORS = ['=', '>=', '>', '<=', '<', '<>'];

    //(...)

    public function __construct($id = null)
    {
        $this->id = $id;
    }
    
    //(...)
}

Teraz metoda find:

abstract class Model {
    
    public $id;
    private $data = array();
    protected static $conn;
    const OPERATORS = ['=', '>=', '>', '<=', '<', '<>'];

    //(...)

    public static function find($id){

        $table = static::$tablename;
        $query = "SELECT * from $table WHERE id = {$id}";

        $q = static::$conn->query($query);
        $params = $q->fetch();

        print_r($params);
      
       }
}

Na chwilę obecną wywołując to z istniejącym ID dostaniemy coś takiego:

PersonModel::find(14);
//Array ( [ID] => 14 [0] => 14 [name] => Jim [1] => Jim [age] => 29 [2] => 29 )

W innym przypadku pusta tablica, i to obsłużyć trzeba:

abstract class Model {
    
    public $id;
    private $data = array();
    protected static $conn;
    const OPERATORS = ['=', '>=', '>', '<=', '<', '<>'];

    //(...)

    public static function find($id){

        $table = static::$tablename;
        $query = "SELECT * from $table WHERE id = {$id}";

        $q = static::$conn->query($query);
        $params = $q->fetch();

        if(!$params)
            return false;
      
       }
}

Możemy var-dumpnąć ze złym ID. Zobaczmy, co daje nam dobry:

PersonModel::find(14);
//Array ( [ID] => 14 [0] => 14 [name] => Jim [1] => Jim [age] => 29 [2] => 29 )

ID trzeba użyć w konstruktorze i olać potem:

abstract class Model {
    
    public $id;
    private $data = array();
    protected static $conn;
    const OPERATORS = ['=', '>=', '>', '<=', '<', '<>'];

    //(...)

    public static function find($id){

        $table = static::$tablename;
        $query = "SELECT * from $table WHERE id = {$id}";

        $q = static::$conn->query($query);
        $params = $q->fetch();

        if(!$params)
            return false;
        
        $model = new static($params['ID']);

        foreach($params as $key => $value){
            if($key === 'ID')
                continue;
        }
        
        return $model;
      
       }
}

Teraz trzeba wypełnić inne pola, olewając klucze numeryczne bo mamy jedne i drugie:

abstract class Model {
    
    public $id;
    private $data = array();
    protected static $conn;
    const OPERATORS = ['=', '>=', '>', '<=', '<', '<>'];

    //(...)

    public static function find($id){

        $table = static::$tablename;
        $query = "SELECT * from $table WHERE id = {$id}";

        $q = static::$conn->query($query);
        $params = $q->fetch();

        if(!$params)
            return false;
        
        $model = new static($params['ID']);

        foreach($params as $key => $value){
            if($key === 'ID')
                continue;
            if(is_numeric($key))
                continue;
            $model->$key = $value;
        }
        
        return $model;
      
       }
}

Już możemy naszego modelu spokojnie używać w ten sposób:

$jim = PersonModel::find(14);
echo $jim->id . "<br>";
echo $jim->name . "<br>";
echo $jim->age . "<br>";

Dodam, że ten „new static” to jest właśnie utworzenie obiektu klasy PersonModel z pozycji klasy Model. Czemu tak?

Bo tak:

class PersonModel extends Model {

    protected static $tablename = 'people';
    protected static $keys = ['name', 'age'];
 
}

To jest nasze modele mają być proste w użyciu, dwie rzeczy do wypełnienia i można używać. Ciężka logika jest zapisana w klasie Model, klasie bazowej.