Rozbudowa naszego modelu – tym razem dodajemy do niego paginację, znanym już nam sposobem. Do dzieła.

Najpierw metoda lastPage:

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

    //(...)

    public static function count(){
        $table = static::$tablename;
        $query = "SELECT COUNT(*) FROM {$table}";
        $q = static::$conn->query($query);
        return $q->fetch()[0]; 
    }

    public static function lastPage($perPage){
        $count = static::count();
        $lastPage = ceil($count / $perPage);
        return $lastPage;
    }

}

Metoda lastPage wykorzystuje count i wylicza znanym nam wzorem ostatnią stronę dla takiej ilości elementów na każdą.

Sprawdźmy:

//(...)

class PersonModel extends Model {

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

$person = new PersonModel();
$person->setConn($conn);

echo PersonModel::lastPage(5);
//3

Teraz metoda paginate:

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

    //(...)

    public static function paginate(int $page, int $perPage = 5) {
        $table = static::$tablename;

        $page = max(1, $page);
        $lastPage = static::lastPage($perPage);
        $page = min($page, $lastPage);

        $stmt = static::$conn->prepare("SELECT * 
            FROM {$table} 
            ORDER BY `ID` ASC
            LIMIT :limit OFFSET :offset");

        $stmt->bindValue(':limit', $perPage, PDO::PARAM_INT);
        $stmt->bindValue(':offset', ($page - 1) * $perPage, PDO::PARAM_INT);

        $stmt->execute();
        $entries = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        return $entries;

    }

}

Ok, działa to tak:

echo PersonModel::lastPage(5);
//3

print_r(PersonModel::paginate(3,5));
//strona 3

print_r(PersonModel::paginate(4,5));
//też strona 3

print_r(PersonModel::paginate(-3,5));
//strona 1

Omawialiśmy paginację w lekcji o Repository Pattern, więc powtarzać się nie będziemy…