Przerzucamy metody z klasy pochodnej do klasy bazowej. Rozbudowa naszego projektu MVC. Do dzieła.

Najpierw rzućmy okiem na klasy z poprzedniej lekcji:

abstract class Model {

    protected static $conn;

    public static function setConn($conn)
    {
        static::$conn = $conn;
    }

    public static function keysString(){
        return "(" . implode(", ", static::$keys) . ")";
    }

    public static function valuesString(){
        $values = array_map(fn($k) => ":$k", static::$keys);
        return "(" . implode(", ", $values) . ")";
    }

    abstract public static  function insert($data);

}

class PersonModel extends Model {

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

    public static function insert($data){
        $table = self::$tablename;
        $keys = static::keysString();
        $vals = static::valuesString();
        $query = "INSERT INTO {$table} {$keys} VALUES {$vals}";
        $stmt = static::$conn->prepare($query);   
        return $stmt->execute($data);
    }

    public static function all($type=PDO::FETCH_OBJ){
        $table = self::$tablename;
        $query = "SELECT * FROM $table";
        $stmt = static::$conn->prepare($query);
        $stmt->execute();
        return $stmt->fetchAll($type);
    }
}

Czy przy każdym modelu chcemy implementować insert i all? Jeżeli nie, przenosimy to do klasy bazowej:

abstract class Model {

    protected static $conn;

    public static function setConn($conn)
    {
        static::$conn = $conn;
    }

    public static function keysString(){
        return "(" . implode(", ", static::$keys) . ")";
    }

    public static function valuesString(){
        $values = array_map(fn($k) => ":$k", static::$keys);
        return "(" . implode(", ", $values) . ")";
    }

    public static function insert($data){
        $table = static::$tablename;
        $keys = static::keysString();
        $vals = static::valuesString();
        $query = "INSERT INTO {$table} {$keys} VALUES {$vals}";
        $stmt = static::$conn->prepare($query);   
        return $stmt->execute($data);
    }

    public static function all($type=PDO::FETCH_OBJ){
        $table = static::$tablename;
        $query = "SELECT * FROM $table";
        $stmt = static::$conn->prepare($query);
        $stmt->execute();
        return $stmt->fetchAll($type);
    }

}

class PersonModel extends Model {

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

    
}

Musieliśmy zamienić self na static – klasa Model nie posiada pola tablename ani keys. Self było dobre, gdy trzymaliśmy te metody w PersonModel, ale to się skończyło.

Mamy natomiast już 2 metody, które do działania potrzebują tylko podania w klasie pochodnej odpowiedniej nazwy tabeli oraz kluczy.

W Laravelu to jest jeszcze łatwiejsze, bo nazwa tabeli jest dedukowana po nazwie modelu, ale w Laravelu jest więcej warstw abstrakcji i trochę nam zajmie czasu, zanim ten poziom osiągniemy.