Przepis na robienie paginacji w PHP, który raz poznany możemy zastosować w każdej sytuacji i używając jakiegokolwiek narzędzia. Do dzieła.
Krok pierwszy – złapać numer strony z query i rzutować do typu int:
$page = $_GET['p'] ?? 1;
$page = (int) $page;
Krok drugi – ustalić długość (ilość elementów per page) i offset według wzoru:
$length = 5;
$offset = ($page - 1) * $length;
Dla takiego wzoru ilość elementów per page dla strony pierwszej to 5 zaś offset to 0 (razy 5).
Druga strona posiada ilość per page 5 oraz offset 5 (razy 1).
SQL wygląda mniej-więcej tak:
SELECT (*)
FROM tablename
LIMIT 5
OFFSET 0
SELECT (*)
FROM tablename
LIMIT 5
OFFSET 5
W omawianym przykładzie łapiemy sobie jeszcze searchTerm oraz rekordy (tymi sqlami) i ilość wszystkich rekordów:
$searchTerm = $_GET['s'] ?? null;
[$transactions, $count] = $this->transactionService->getUserTransactions(
$length,
$offset
);
Ilość wszystkich rekordów zapewnia nam mniej-więcej taki SQL:
SELECT COUNT(*)
FROM tablename
WHERE searchterm
LIKE "%term%"
Oczywiście jeżeli chcemy się bawić w „SEARCH LIKE %” musimy w odpowiedniej metodzie zrobić escape na znaki takie jak „%” na przykład:
public function getUserTransactions(int $length, int $offset)
{
$searchTerm = addcslashes($_GET['s'] ?? '', '%_');
//(...)
Chodzi generalnie o to, aby SQL nie mylił znaku „%” w nazwie poszukiwanego modelu z operatorem SQL.
Tak czy inaczej ostatnią stronę wyliczamy w ten sposób:
$lastPage = ceil($count / $length);
Ilość elementów podzielić na ilość elementów per page równa się ostatnia strona. Może równać się zero, może nie być ostatniej strony.
Mając to na uwadze możemy stworzyć zakres linków z numerami stron:
$lastPage = ceil($count / $length);
$pages = $lastPage ? range(1, $lastPage) : [];
$pageLinks = array_map(
fn ($pageNum) => http_build_query([
'p' => $pageNum,
's' => $searchTerm
]),
$pages
);
Ważna uwaga – PHP to nie Python. To znaczy, że range od 1 do 10 obejmuje 10 (numer ostatniej strony na przykład). Żadnego +1 tam nie potrzebujemy!
We frameworku phpiggy, bo to jego omawiamy, koniec paginacji wygląda tak:
echo $this->view->render("index.php", [
'transactions' => $transactions,
'currentPage' => $page,
'previousPageQuery' => http_build_query([
'p' => $page - 1,
's' => $searchTerm
]),
'lastPage' => $lastPage,
'nextPageQuery' => http_build_query([
'p' => $page + 1,
's' => $searchTerm
]),
'pageLinks' => $pageLinks,
'searchTerm' => $searchTerm
]);
Prawdę powiedziawszy – poznaliśmy patent na zrobienie paginacji w dowolnym frameworku (także własnym) a nawet bez niego.
Wszystko rozkłada się o zrozumienie kilku podstawowych konceptów i złożenie tego do kupy nie popełniając głupich błędów.