Heim >Backend-Entwicklung >PHP-Tutorial >Ein Leitfaden zur Paginierung in Laravel
Pagination ist eine gemeinsame Funktion in Webanwendungen. Fast jede Laravel -Anwendung, an der ich jemals gearbeitet habe
Aber was ist Pagination und warum benutzen wir es? Wie können wir Paginierung in unseren Laravel -Anwendungen implementieren? Und wie entscheiden wir, welche Pagierungsmethode verwendet werden soll?In diesem Artikel werden wir genau diese Fragen beantworten und untersuchen, wie Pagination in Laravel sowohl für Blade -Ansichten als auch für API -Endpunkte verwendet wird. Am Ende dieses Artikels sollten Sie sich sicher genug fühlen, um in Ihren eigenen Projekten eine Paginierung zu verwenden.
#Was ist Pagination?
Stellen Sie sich beispielsweise vor, Sie hätten eine Seite, die die Namen aller Benutzer in Ihrer Anwendung ausgibt. Wenn Sie Tausende von Benutzern hätten, wäre es nicht praktisch, sie alle auf einer einzigen Seite anzuzeigen. Stattdessen können Sie auf jeder Seite Pagination verwenden, um eine Teilmenge der Benutzer (z.
Durch Verwendung von Pagination können Sie:
Verbesserung der Leistung Ihrer Anwendung - Da Sie gleichzeitig eine kleinere Teilmenge von Daten abrufen, müssen Sie weniger Daten aus der Datenbank abholen, sich verarbeiten und dann zurückgeben.
Offset -basierte Pagination - Dies ist die häufigste Art von Pagination, auf die Sie wahrscheinlich in Ihren Web -Apps stoßen, insbesondere in Benutzeroberflächen (UI). Dazu gehören eine Teilmenge von Daten aus der Datenbank basierend auf einem "Offset" und einer "Grenze". Zum Beispiel können Sie 10 Datensätze ab dem 20. Datensatz abrufen, um die 3. Datenseite abzurufen.
paginate
- Verwendet eine Offset -basierte Pagination und holt die Gesamtzahl der Datensätze im Datensatz ab. simplePaginate
- Verwendet eine Offset -basierte Pagination, holt aber nicht die Gesamtzahl der Datensätze im Datensatz. cursorPaginate
- Verwendet Cursor -basierter Pagination und holt nicht die Gesamtzahl der Datensätze im Datensatz. Schauen wir uns jede dieser Methoden ausführlicher an.
paginate
-Methode Mit der Methode paginate
können Sie eine Teilmenge von Daten aus der Datenbank basierend auf einem Offset und Grenzwert abrufen (wir werden uns später ansehen, wenn wir uns die zugrunde liegenden SQL -Abfragen ansehen).
Sie können die paginate
-Methode wie SO verwenden:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
Ausführen des obigen Codes würde dazu führen, dass $users
eine Instanz von IlluminateContractsPaginationLengthAwarePaginator
ist, typischerweise ein IlluminatePaginationLengthAwarePaginator
Objekt. Diese Paginatorinstanz enthält alle Informationen, die Sie für die Anzeige der pagierten Daten in Ihrer Anwendung benötigen.
Die Methode paginate
kann die angeforderte Seitennummer automatisch basierend auf dem Parameter page
Abfrage in der URL ermitteln. Wenn Sie beispielsweise https://my-app.com/users?page=2
besucht haben, würde die paginate
-Methode die zweite Seite der Daten abrufen.
standardmäßig sind alle Paginierungsmethoden in Laravel standardmäßig 15 Datensätze gleichzeitig abgerufen. Dies kann jedoch in einen anderen Wert geändert werden (wir werden uns später ansehen, wie dies später geht).
paginate
mit Blade -Ansichten Schauen wir uns an, wie die paginate
-Methode verwendet wird, wenn Daten in einer Klingenansicht rendern.
Stellen Sie sich vor, wir haben eine einfache Route, die die Benutzer aus der Datenbank in einem pagierten Format abruft und sie an eine Ansicht weitergibt:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('users', function () { $users = User::query()->paginate(); return view('users.index', [ 'users' => $users, ]); });
unsere resources/views/users/index.blade.php
Datei könnte ungefähr so aussehen:
<!-- Syntax highlighted by torchlight.dev --><html> <head> <title>Paginate</title> <script src="https://cdn.tailwindcss.com"></script> </head> <body> <div class="max-w-5xl mx-auto py-8"> <h1 class="text-5xl">Paginate</h1> <ul class="py-4"> @foreach ($users as $user) <li class="py-1 border-b">{{ $user->name }}</li> @endforeach </ul> {{ $users->links() }} </div> </body> </html>
Die resultierende Seite würde ungefähr so aussehen:
Lassen Sie uns zusammenbrechen, was in der Klingeansicht passiert:
$users
(das IlluminatePaginationLengthAwarePaginator
-Objekt) vorhanden ist und seinen Namen ausgibt. links
-Methode im $users
-Objekt. Dies ist eine wirklich praktische Methode, die einige HTML zurückgibt, die die Paginierungslinks (z. B. "vorher", "Next" und die Seitennummern anzeigen). Dies bedeutet
-Methode uns einen Überblick über die Paginierungsdaten gibt. Wir können sehen, dass wir die 16. bis 30. Rekorde von insgesamt 50 Datensätzen betrachten. Wir können auch sehen, dass wir auf der zweiten Seite sind und dass es insgesamt 4 Seiten gibt. paginate
-Methode das HTML -Stil mit dem Rückenwind -CSS zurückgibt. Wenn Sie etwas anderes als Rückenwind verwenden möchten oder die Paginierungsverlinks selbst stylen möchten, können Sie die Dokumentation zum Anpassen von Paginationsansichten überprüfen. links
paginate
-Methode in Blade -Ansichten verwenden Sie sie auch in den API -Endpunkten. Laravel erleichtert diesen Vorgang durch automatische Konvertierung der pagierten Daten in JSON. paginate
-Dendpunkt erstellen (indem wir die folgende Route zu unserer /api/users
-Datei hinzufügen), die die pagierten Benutzer im JSON -Format zurückgibt: routes/api.php
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();Zugriff auf den Endpunkt
würde eine JSON -Antwort zurückgeben, die dem folgenden ähnlich ist
/api/users
data
Lassen Sie uns die JSON -Antwort aufschlüsseln:
current_page
- Die aktuelle Seite, auf der wir uns befinden. In diesem Fall sind wir auf der ersten Seite. data
- Die tatsächlichen Daten selbst, die zurückgegeben werden. In diesem Fall enthält es die ersten 15 Benutzer (verkürzt auf 3 für Kürze). first_page_url
- Die URL zur ersten Datenseite. from
- Die Startdatensatznummer der zurückgegebenen Daten. In diesem Fall ist es der erste Rekord. Wenn wir auf der zweiten Seite wären, wäre dies 16. last_page
- Die Gesamtzahl der Datenseiten. In diesem Fall gibt es 4 Seiten. last_page_url
- Die URL zur letzten Datenseite. links
- Ein Array von Links zu den verschiedenen Datenseiten. Dies umfasst die "vorherigen" und "nächsten" Links sowie die Seitenzahlen. next_page_url
- Die URL zur nächsten Datenseite. path
- Die Basis -URL des Endpunkts. per_page
- Die Anzahl der zurückgegebenen Datensätze pro Seite. In diesem Fall ist es 15. prev_page_url
- Die URL zur vorherigen Datenseite. In diesem Fall ist es null
, weil wir auf der ersten Seite sind. Wenn wir auf der zweiten Seite wären, wäre dies die URL zur ersten Seite. to
- Die Enddatensatznummer der zurückgegebenen Daten. In diesem Fall ist es der 15. Rekord. Wenn wir auf der zweiten Seite wären, wäre dies 30. total
- Die Gesamtzahl der Datensätze im Datensatz. In diesem Fall gibt es 50 Datensätze. Verwenden der paginate
-Methode in Laravel führt zu zwei SQL -Abfragen:
Wenn wir also die erste Seite von Benutzern (mit 15 Benutzern pro Seite) abrufen wollten, werden die folgenden SQL -Abfragen ausgeführt:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
und
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('users', function () { $users = User::query()->paginate(); return view('users.index', [ 'users' => $users, ]); });
In der zweiten Abfrage können wir sehen, dass der Wert limit
auf 15 gesetzt ist. Dies ist die Anzahl der Datensätze, die pro Seite zurückgegeben werden.
Der Wert offset
wird wie folgt berechnet:
<!-- Syntax highlighted by torchlight.dev --><html> <head> <title>Paginate</title> <script src="https://cdn.tailwindcss.com"></script> </head> <body> <div class="max-w-5xl mx-auto py-8"> <h1 class="text-5xl">Paginate</h1> <ul class="py-4"> @foreach ($users as $user) <li class="py-1 border-b">{{ $user->name }}</li> @endforeach </ul> {{ $users->links() }} </div> </body> </html>
Wenn wir also die dritte Seite der Benutzer holen wollten, wird der Wert offset
berechnet als:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('paginate', function () { return User::query()->paginate(); });
Daher wäre der Wert offset
30 und wir würden die 31. bis 45. Datensätze holen. Die Abfragen für die dritte Seite würden so aussehen:
<!-- Syntax highlighted by torchlight.dev -->{ "current_page": 1, "data": [ { "id": 1, "name": "Andy Runolfsson", "email": "teresa.wiegand@example.net", "email_verified_at": "2024-10-15T23:19:28.000000Z", "created_at": "2024-10-15T23:19:29.000000Z", "updated_at": "2024-10-15T23:19:29.000000Z" }, { "id": 2, "name": "Rafael Cummings", "email": "odessa54@example.org", "email_verified_at": "2024-10-15T23:19:28.000000Z", "created_at": "2024-10-15T23:19:29.000000Z", "updated_at": "2024-10-15T23:19:29.000000Z" }, { "id": 3, "name": "Reynold Lindgren", "email": "juwan.johns@example.net", "email_verified_at": "2024-10-15T23:19:28.000000Z", "created_at": "2024-10-15T23:19:29.000000Z", "updated_at": "2024-10-15T23:19:29.000000Z" } ], "first_page_url": "http://example.com/users?page=1", "from": 1, "last_page": 4, "last_page_url": "http://example.com/users?page=4", "links": [ { "url": null, "label": "« Previous", "active": false }, { "url": "http://example.com/users?page=1", "label": "1", "active": true }, { "url": "http://example.com/users?page=2", "label": "2", "active": false }, { "url": "http://example.com/users?page=3", "label": "3", "active": false }, { "url": "http://example.com/users?page=4", "label": "4", "active": false }, { "url": "http://example.com/users?page=5", "label": "5", "active": false }, { "url": "http://example.com/users?page=2", "label": "Next »", "active": false } ], "next_page_url": "http://example.com/users?page=2", "path": "http://example.com/users", "per_page": 15, "prev_page_url": null, "to": 15, "total": 50 }
und
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
simplePaginate
-Methode Die simplePaginate
-Methode ist der paginate
-Methode jedoch sehr ähnlich, jedoch mit einem Schlüsselunterschied. Die simplePaginate
-Methode holt nicht die Gesamtzahl der Datensätze im Datensatz ab.
Wie wir gerade gesehen haben, erhalten wir, wenn wir die paginate
-Methode verwenden, auch Informationen über die Gesamtzahl der im Datensatz verfügbaren Datensätze und Seiten. Wir können diese Informationen dann verwenden, um Dinge wie die Gesamtzahl der Seiten in der UI- oder API -Antwort anzuzeigen.
Wenn Sie diese Details jedoch nicht dem Benutzer (oder Entwickler, der die API verbraucht), können wir eine nicht benötigte Datenbankabfrage vermeiden (die die Gesamtzahl der Datensätze zählt) mithilfe der Methode simplePaginate
.
Die simplePaginate
-Methode kann auf die gleiche Weise wie die paginate
-Methode verwendet werden:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('users', function () { $users = User::query()->paginate(); return view('users.index', [ 'users' => $users, ]); });
Ausführen des obigen Code
$users
Im Gegensatz zu dem von der IlluminateContractsPaginationPaginator
-Methode zurückgegebenen IlluminatePaginationPaginator
-Objekt enthält das Objekt
IlluminatePaginationLengthAwarePaginator
#use paginate
mit Blade -Ansichten IlluminatePaginationPaginator
simplePaginate
simplePaginate
simplePaginate
Die resultierende Seite würde ungefähr so aussehen:
<!-- Syntax highlighted by torchlight.dev --><html> <head> <title>Paginate</title> <script src="https://cdn.tailwindcss.com"></script> </head> <body> <div class="max-w-5xl mx-auto py-8"> <h1 class="text-5xl">Paginate</h1> <ul class="py-4"> @foreach ($users as $user) <li class="py-1 border-b">{{ $user->name }}</li> @endforeach </ul> {{ $users->links() }} </div> </body> </html>
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('paginate', function () { return User::query()->paginate(); });
Wie wir in diesem Beispiel sehen können, unterscheidet sich die Ausgabe von
von der Ausgabe, die wir bei der Verwendung der -Methode gesehen haben. Da die Methode die Gesamtzahl der Datensätze nicht abreißt, hat sie keinen Kontext der Gesamtzahl der Seiten oder Datensätze, nur ob es eine nächste Seite gibt oder nicht. Daher sehen wir nur die "vorherigen" und "nächsten" Links in den Paginationslinks.
In den API -Endpunkten $users->links()
paginate
Sie können auch die simplePaginate
-Methode in den API -Endpunkten verwenden. Laravel konvertiert die pagierten Daten automatisch in JSON für Sie.
simplePaginate
-Getriebe, der die pagierten Benutzer im JSON -Format zurücksetzt: <!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
Wenn wir diese Route erreichen, erhalten wir eine JSON -Antwort ähnlich wie folgt (ich habe das Feld data
auf nur 3 Datensätze für die Kürze beschränkt):
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('users', function () { $users = User::query()->paginate(); return view('users.index', [ 'users' => $users, ]); });
Wie wir sehen können, ist die JSON -Antwort der Antwort sehr ähnlich, die wir bei der Verwendung der paginate
-Methode erhalten haben. Der Hauptunterschied besteht
last_page
#Die zugrunde liegende SQL -Abfragen last_page_url
links
Schauen wir uns die zugrunde liegenden SQL -Abfragen an, die bei Verwendung der total
-Methode ausgeführt werden.
und simplePaginate
, um die Teilmenge der Daten aus der Datenbank abzurufen. Die Abfrage wird jedoch nicht ausgeführt, um die Gesamtzahl der Datensätze im Datensatz abzurufen.
Der Wert simplePaginate
wird weiterhin auf die gleiche Weise berechnet wie zuvor: limit
offset
-Werwert geringfügig unterschiedlich berechnet als die offset
-Methode. Es wird berechnet als:
<!-- Syntax highlighted by torchlight.dev --><html> <head> <title>Paginate</title> <script src="https://cdn.tailwindcss.com"></script> </head> <body> <div class="max-w-5xl mx-auto py-8"> <h1 class="text-5xl">Paginate</h1> <ul class="py-4"> @foreach ($users as $user) <li class="py-1 border-b">{{ $user->name }}</li> @endforeach </ul> {{ $users->links() }} </div> </body> </html>
Dies liegt daran, dass die limit
-Methode einen weiteren Datensatz als den paginate
-Werte abrufen muss, um festzustellen, ob mehr Datensätze abgerufen werden müssen. Angenommen, wir holen 15 Datensätze pro Seite. Der Wert
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('paginate', function () { return User::query()->paginate(); });
Wenn wir also die erste Seite von Benutzern (mit 15 Benutzern pro Seite) abrufen wollten, werden die folgenden SQL -Abfragen ausgeführt: simplePaginate
perPage
limit
Die Abfrage für die zweite Seite würde so aussehen:
#Die
<!-- Syntax highlighted by torchlight.dev -->{ "current_page": 1, "data": [ { "id": 1, "name": "Andy Runolfsson", "email": "teresa.wiegand@example.net", "email_verified_at": "2024-10-15T23:19:28.000000Z", "created_at": "2024-10-15T23:19:29.000000Z", "updated_at": "2024-10-15T23:19:29.000000Z" }, { "id": 2, "name": "Rafael Cummings", "email": "odessa54@example.org", "email_verified_at": "2024-10-15T23:19:28.000000Z", "created_at": "2024-10-15T23:19:29.000000Z", "updated_at": "2024-10-15T23:19:29.000000Z" }, { "id": 3, "name": "Reynold Lindgren", "email": "juwan.johns@example.net", "email_verified_at": "2024-10-15T23:19:28.000000Z", "created_at": "2024-10-15T23:19:29.000000Z", "updated_at": "2024-10-15T23:19:29.000000Z" } ], "first_page_url": "http://example.com/users?page=1", "from": 1, "last_page": 4, "last_page_url": "http://example.com/users?page=4", "links": [ { "url": null, "label": "« Previous", "active": false }, { "url": "http://example.com/users?page=1", "label": "1", "active": true }, { "url": "http://example.com/users?page=2", "label": "2", "active": false }, { "url": "http://example.com/users?page=3", "label": "3", "active": false }, { "url": "http://example.com/users?page=4", "label": "4", "active": false }, { "url": "http://example.com/users?page=5", "label": "5", "active": false }, { "url": "http://example.com/users?page=2", "label": "Next »", "active": false } ], "next_page_url": "http://example.com/users?page=2", "path": "http://example.com/users", "per_page": 15, "prev_page_url": null, "to": 15, "total": 50 }-Methode
verwenden
Bisher haben wir uns die Methoden<!-- Syntax highlighted by torchlight.dev -->select count(*) as aggregate from `users`und
cursorPaginate
-Methode ansehen, die Cursor-basierte Pagination verwendet. Als Heads-up scheint der Cursor-basierte Pagination ein wenig verwirrend zu sein, wenn Sie zum ersten Mal darauf stoßen. Machen Sie sich also keine Sorgen, wenn Sie es nicht sofort verstehen. Hoffentlich werden Sie am Ende dieses Artikels ein besseres Verständnis dafür haben, wie es funktioniert. Ich werde am Ende dieses Artikels auch ein fantastisches Video hinterlassen, in dem der Cursor-basierte Pagination ausführlicher erklärt wird. paginate
simplePaginate
Mit einer offset-basierten Pagination verwenden wir die Werte cursorPaginate
und
Nehmen wir zum Beispiel an, wir machen eine Frage, um die ersten 15 Benutzer abzurufen. Wir gehen davon aus, dass die ID des 15. Benutzers 20 ist. Wenn wir die nächsten 15 Benutzer abrufen möchten, verwenden wir die ID des 15. Benutzers (20) als Cursor. Wir werden sagen "Die nächsten 15 Benutzer mit einer ID von mehr als 20 abrufen".
Sie können manchmal Cursors sehen, die als "Token", "Keys", "Next", "vorher" und so weiter bezeichnet werden. Sie sind im Wesentlichen ein Verweis auf einen bestimmten Datensatz in der Datenbank. Wir werden uns die Struktur der Cursoren später in diesem Abschnitt ansehen, wenn wir uns die zugrunde liegenden SQL -Abfragen ansehen.
Mit Laravel können wir die Cursor-basierte Pagination mit der cursorPaginate
-Methode leicht verwenden:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
Ausführen des obigen Codes würde dazu führen, dass das Feld $users
eine Instanz von IlluminateContractsPaginationCursorPaginator
ist, typischerweise ein IlluminatePaginationCursorPaginator
-Objekt. Diese Paginatorinstanz enthält alle Informationen, die Sie für die Anzeige der pagierten Daten in Ihrer Anwendung benötigen.
Ähnlich wie bei der simplePaginate
-Methode fördert die cursorPaginate
-Methode nicht die Gesamtzahl der Datensätze im Datensatz. Es kennt nur die aktuelle Datenseite und darüber, ob mehr Datensätze abgerufen werden müssen. Daher sind wir uns nicht sofort der Gesamtzahl der Seiten oder Datensätze bewusst.
cursorPaginate
mit Blade -Ansichten Schauen wir uns an, wie Sie die cursorPaginate
-Methode verwenden, wenn Daten in einer Klingenansicht rendern. Ähnlich wie bei unseren früheren Beispielen werden wir annehmen, dass wir eine einfache Route haben, die die Benutzer aus der Datenbank in einem paginierten Format abreißt und sie an eine Ansicht weitergibt:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('users', function () { $users = User::query()->paginate(); return view('users.index', [ 'users' => $users, ]); });
Die Klingeansicht könnte ungefähr so aussehen:
<!-- Syntax highlighted by torchlight.dev --><html> <head> <title>Paginate</title> <script src="https://cdn.tailwindcss.com"></script> </head> <body> <div class="max-w-5xl mx-auto py-8"> <h1 class="text-5xl">Paginate</h1> <ul class="py-4"> @foreach ($users as $user) <li class="py-1 border-b">{{ $user->name }}</li> @endforeach </ul> {{ $users->links() }} </div> </body> </html>
Dies würde eine Seite ähnlich wie folgt ausgeben:
Wie wir sehen können, ist die Ausgabe von cursorPaginate
nicht die Gesamtzahl der Datensätze im Datensatz $users->links()
, da die Ausgabe von simplePaginate
bei der Verwendung der
cursorPaginate
#using
Mit cursorPaginate
Laravel können Sie auch die Methode
/api/users
Erstellen wir einen
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('paginate', function () { return User::query()->paginate(); });
data
Wenn wir diese Route erreichen, erhalten wir eine JSON -Antwort ähnlich wie folgt (ich habe das Feld
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
Wie wir sehen können, ähnelt die JSON -Antwort den vorherigen Antworten, die wir gesehen haben, jedoch mit einigen kleinen Unterschieden. Da wir nicht die Gesamtzahl der Datensätze abrufen, haben wir nicht die Felder last_page
, last_page_url
, links
oder total
in der Antwort. Möglicherweise haben Sie auch bemerkt, dass wir auch nicht die Felder from
und to
haben.
Stattdessen haben wir die Felder next_cursor
und prev_cursor
, die den Cursor für die nächsten und vorherigen Datenseiten enthalten. Da wir auf der ersten Seite sind, sind die Felder prev_cursor
und prev_page_url
beide null
. Die Felder next_cursor
und next_page_url
sind jedoch festgelegt.
Das Feld next_cursor
ist eine base-64-codierte Zeichenfolge, die den Cursor für die nächste Datenseite enthält. Wenn wir das Feld next_cursor
dekodieren, bekommen wir so etwas (für die Lesbarkeit verschönert):
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('users', function () { $users = User::query()->paginate(); return view('users.index', [ 'users' => $users, ]); });
Der Cursor enthält zwei separate Informationen:
users.id
- Die ID des letzten im Datensatzes abgerufenen Datensatzes. _pointsToNextItems
- Ein boolescher Wert, der uns zeigt, ob der Cursor auf die nächste oder vorherige Elemente hinweist. Wenn der Wert true
ist, bedeutet dies, dass der Cursor verwendet werden sollte, um den nächsten Satz von Datensätzen mit einer ID zu holen, die größer als der users.id
-Werte ist. Wenn der Wert false
ist, bedeutet dies, dass der Cursor verwendet werden sollte, um den vorherigen Satz von Datensätzen mit einer ID unter dem Wert users.id
abzurufen. Schauen wir uns an, wie die zweite Seite der Daten aussehen könnte (erneut verkürzt auf 3 Datensätze für die Kürze):
<!-- Syntax highlighted by torchlight.dev --><html> <head> <title>Paginate</title> <script src="https://cdn.tailwindcss.com"></script> </head> <body> <div class="max-w-5xl mx-auto py-8"> <h1 class="text-5xl">Paginate</h1> <ul class="py-4"> @foreach ($users as $user) <li class="py-1 border-b">{{ $user->name }}</li> @endforeach </ul> {{ $users->links() }} </div> </body> </html>
können wir sehen, dass die Felder prev_cursor
und prev_page_url
jetzt festgelegt sind und die Felder next_cursor
und next_page_url
für die nächste Datenseite mit dem Cursor aktualisiert wurden.
Um ein besseres Verständnis dafür zu bekommen, wie die Cursorpagination unter der Haube funktioniert, schauen wir uns die zugrunde liegenden SQL
cursorPaginate
Auf der ersten Datenseite (mit 15 Datensätzen) würde die folgende SQL -Abfrage ausgeführt:
Wir können sehen, dass wir die ersten 16 Datensätze aus der Tabelle
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('paginate', function () { return User::query()->paginate(); });abrufen und sie in der Spalte
in aufsteigender Reihenfolge bestellen. Ähnlich wie bei der users
-Methode holen wir 16 Zeilen, weil wir feststellen möchten, ob mehr Datensätze zum Abrufen sind. id
simplePaginate
Stellen wir uns vor, wir navigieren dann mit dem folgenden Cursor zur nächsten Seite der Elemente:
Wenn dieser Cursor dekodiert ist, erhalten wir das folgende JSON -Objekt:
<!-- Syntax highlighted by torchlight.dev -->{ "current_page": 1, "data": [ { "id": 1, "name": "Andy Runolfsson", "email": "teresa.wiegand@example.net", "email_verified_at": "2024-10-15T23:19:28.000000Z", "created_at": "2024-10-15T23:19:29.000000Z", "updated_at": "2024-10-15T23:19:29.000000Z" }, { "id": 2, "name": "Rafael Cummings", "email": "odessa54@example.org", "email_verified_at": "2024-10-15T23:19:28.000000Z", "created_at": "2024-10-15T23:19:29.000000Z", "updated_at": "2024-10-15T23:19:29.000000Z" }, { "id": 3, "name": "Reynold Lindgren", "email": "juwan.johns@example.net", "email_verified_at": "2024-10-15T23:19:28.000000Z", "created_at": "2024-10-15T23:19:29.000000Z", "updated_at": "2024-10-15T23:19:29.000000Z" } ], "first_page_url": "http://example.com/users?page=1", "from": 1, "last_page": 4, "last_page_url": "http://example.com/users?page=4", "links": [ { "url": null, "label": "« Previous", "active": false }, { "url": "http://example.com/users?page=1", "label": "1", "active": true }, { "url": "http://example.com/users?page=2", "label": "2", "active": false }, { "url": "http://example.com/users?page=3", "label": "3", "active": false }, { "url": "http://example.com/users?page=4", "label": "4", "active": false }, { "url": "http://example.com/users?page=5", "label": "5", "active": false }, { "url": "http://example.com/users?page=2", "label": "Next »", "active": false } ], "next_page_url": "http://example.com/users?page=2", "path": "http://example.com/users", "per_page": 15, "prev_page_url": null, "to": 15, "total": 50 }
Laravel wird dann die folgende SQL -Abfrage ausführen, um den nächsten Satz von Datensätzen abzurufen:
<!-- Syntax highlighted by torchlight.dev -->select count(*) as aggregate from `users`
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
Wie wir sehen können, holen wir die nächsten 16 Datensätze aus der Tabelle users
mit einem id
größer als 15 (da 15 die letzte ID auf der vorherigen Seite war).
Nehmen wir nun an, dass die ID des ersten Benutzers auf Seite 2 16 ist. Wenn wir zurück zur ersten Datenseite der zweiten Seite navigieren, würde der folgende Cursor verwendet:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('users', function () { $users = User::query()->paginate(); return view('users.index', [ 'users' => $users, ]); });
Wenn dies dekodiert ist, erhalten wir das folgende JSON -Objekt:
<!-- Syntax highlighted by torchlight.dev --><html> <head> <title>Paginate</title> <script src="https://cdn.tailwindcss.com"></script> </head> <body> <div class="max-w-5xl mx-auto py-8"> <h1 class="text-5xl">Paginate</h1> <ul class="py-4"> @foreach ($users as $user) <li class="py-1 border-b">{{ $user->name }}</li> @endforeach </ul> {{ $users->links() }} </div> </body> </html>
Wenn wir zur nächsten Ergebnisse übergehen, wird der letzte abgerufene Datensatz als Cursor verwendet. Wenn wir zur vorherigen Ergebnisse zurückkehren, wird der erste abgerufene Datensatz als Cursor verwendet. Aus diesem Grund können wir sehen, dass der Wert users.id
im Cursor auf 16 eingestellt ist. Wir können auch sehen, dass der Wert _pointsToNextItems
auf false
festgelegt wird, da wir zu den vorherigen Elementen zurückkehren.
Infolgedessen würde die folgende SQL -Abfrage ausgeführt, um den vorherigen Satz von Datensätzen zu holen:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('paginate', function () { return User::query()->paginate(); });
Wie wir sehen können, prüft die Einschränkung where
nun auf Datensätze mit einem id
weniger als 16 (da 16 die erste ID auf Seite 2 war) und die Ergebnisse in absteigender Reihenfolge bestellt werden.
In unseren API -Beispielen haben wir bisher die paginierten Daten direkt vom Controller zurückgegeben. In einer realen Anwendung möchten Sie jedoch wahrscheinlich die Daten verarbeiten, bevor Sie sie an den Benutzer zurückgeben. Dies kann alles aus dem Hinzufügen oder Entfernen von Feldern, dem Konvertieren von Datentypen oder sogar von der Umwandlung der Daten in ein anderes Format sein. Aus diesem Grund möchten Sie wahrscheinlich API -Ressourcen verwenden, da sie eine Möglichkeit bieten, Ihre Daten konsequent zu transformieren, bevor sie diese zurückgeben.
MitLaravel können Sie API -Ressourcen neben Pagination verwenden. Schauen wir uns ein Beispiel dafür an, wie es geht.
Stellen Sie sich vor, wir haben eine AppHttpResourcesUserResource
API -Ressourcenklasse erstellt, die die Benutzerdaten vor der Rückgabe transformiert. Es könnte ungefähr so aussehen:
<!-- Syntax highlighted by torchlight.dev -->{ "current_page": 1, "data": [ { "id": 1, "name": "Andy Runolfsson", "email": "teresa.wiegand@example.net", "email_verified_at": "2024-10-15T23:19:28.000000Z", "created_at": "2024-10-15T23:19:29.000000Z", "updated_at": "2024-10-15T23:19:29.000000Z" }, { "id": 2, "name": "Rafael Cummings", "email": "odessa54@example.org", "email_verified_at": "2024-10-15T23:19:28.000000Z", "created_at": "2024-10-15T23:19:29.000000Z", "updated_at": "2024-10-15T23:19:29.000000Z" }, { "id": 3, "name": "Reynold Lindgren", "email": "juwan.johns@example.net", "email_verified_at": "2024-10-15T23:19:28.000000Z", "created_at": "2024-10-15T23:19:29.000000Z", "updated_at": "2024-10-15T23:19:29.000000Z" } ], "first_page_url": "http://example.com/users?page=1", "from": 1, "last_page": 4, "last_page_url": "http://example.com/users?page=4", "links": [ { "url": null, "label": "« Previous", "active": false }, { "url": "http://example.com/users?page=1", "label": "1", "active": true }, { "url": "http://example.com/users?page=2", "label": "2", "active": false }, { "url": "http://example.com/users?page=3", "label": "3", "active": false }, { "url": "http://example.com/users?page=4", "label": "4", "active": false }, { "url": "http://example.com/users?page=5", "label": "5", "active": false }, { "url": "http://example.com/users?page=2", "label": "Next »", "active": false } ], "next_page_url": "http://example.com/users?page=2", "path": "http://example.com/users", "per_page": 15, "prev_page_url": null, "to": 15, "total": 50 }
In der Methode toArray
definieren wir, dass wir, wenn wir einen Benutzer über diese Ressource verarbeiten, nur die Felder id
, name
und email
zurückgeben möchten.
Erstellen wir nun einen einfachen /api/users
API -Endpunkt in unserer routes/api.php
-Datei, die die paginierten Benutzer mithilfe des AppHttpResourcesUserResource
:
<!-- Syntax highlighted by torchlight.dev -->select count(*) as aggregate from `users`
im obigen Code holen wir eine einzige Seite von Benutzern (nehmen wir an, es ist die erste Seite mit 15 Benutzern) aus der Datenbank. Wir übergeben dann das Feld $users
(das eine Instanz von IlluminatePaginationLengthAwarePaginator
) an die UserResource::collection
-Methode sein wird. Diese Methode transformiert die paginierten Daten mithilfe der AppHttpResourcesUserResource
, bevor sie an den Benutzer zurückgegeben wird.
Wenn wir auf den Endpunkt /api/users
klicken, erhalten wir eine JSON -Antwort ähnlich wie folgt (ich habe das Feld data
auf nur 3 Datensätze für die Kürze eingeschränkt):
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
Wie wir im obigen JSON sehen können, erkennt Laravel, dass wir mit einem pagierten Datensatz arbeiten und die pagierten Daten wie zuvor in einem ähnlichen Format zurückgeben. Diesmal enthalten die Benutzer im Feld data
jedoch nur die Felder id
, name
und email
, die wir in unserer API -Ressourcenklasse angegeben haben. Andere Felder (current_page
, from
, last_page
, links
, path
, per_page
, to
und total
) werden immer noch zurückgegeben, da sie Teil der paginierten Daten sind, aber sie wurden in einem meta
-Feld platziert. Es gibt auch ein links
Feld, das die Links first
, last
, prev
und next
enthält, zu den verschiedenen Datenseiten.
Beim Erstellen von Ansichten mit paginierten Daten möchten Sie dem Benutzer möglicherweise ermöglichen, die Anzahl der pro Seite angezeigten Datensätze zu ändern. Dies kann über ein Dropdown- oder Zahlen -Eingangsfeld geschehen.
laravel erleichtert die Anzahl der pro Seite angezeigten Datensätze, indem ein perPage
-Parameter an die Methoden simplePaginate
, paginate
und cursorPaginate
übergeben wird. Mit diesem Parameter können Sie die Anzahl der Datensätze angeben, die Sie pro Seite anzeigen möchten.
Schauen wir uns ein einfaches Beispiel dafür an, wie Sie einen per_page
-Anterfrageparameter lesen und diese verwenden, um die Anzahl der pro Seite abgerufenen Datensätze zu ändern:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('users', function () { $users = User::query()->paginate(); return view('users.index', [ 'users' => $users, ]); });
Im obigen Beispiel greifen wir den Wert des Parameters per_page
abfragen. Wenn der Wert nicht bereitgestellt wird, werden wir standardmäßig 10. Dann übergeben wir diesen Wert an den Parameter perPage
der Methode paginate
.
wir konnten dann auf diese verschiedenen URLs zugreifen:
https://my-app.com/users
- Zeigen Sie die erste Seite von Benutzern mit 10 Datensätzen pro Seite an. https://my-app.com/users?per_page=5
- Zeigen Sie die erste Seite von Benutzern mit 5 Datensätzen pro Seite an. https://my-app.com/users?per_page=5&page=2
- Zeigen Sie die zweite Seite von Benutzern mit 5 Datensätzen pro Seite an. Nachdem wir uns die verschiedenen Arten von Pagination angesehen haben und wie sie in Laravel verwendet werden, werden wir diskutieren, wie Sie entscheiden können, welche dieser Ansätze in Ihrer Anwendung verwendet werden sollen.
Wenn Sie einen UI- oder API -Endpunkt erstellen, bei dem die Gesamtzahl der Datensätze oder Seiten angezeigt werden muss, ist die Methode paginate
wahrscheinlich eine vernünftige Wahl.
Wenn Sie keine von diesen benötigen, ist die simplePaginate
oder cursorPaginate
effizienter, da sie keine unnötigen Abfragen ausführen, um die Gesamtzahl der Datensätze zu zählen.
Wenn Sie in der Lage sein müssen, auf eine bestimmte Datenseite zu springen, ist eine offset-basierte Pagination besser geeignet. Da der Cursor -Pagination staatlich ist, basiert es auf der vorherigen Seite, um zu wissen, wohin Sie als nächstes gehen sollen. Es ist also nicht so einfach, zu einer bestimmten Seite zu springen.
Während Sie bei der Verwendung von Offset -Pagination die Seitennummer in der Anforderung (möglicherweise als Abfrageparameter) übergeben und zu dieser Seite springen, ohne einen Kontext der vorherigen Seite zu haben.
Aufgrund der Art und Weise, wie Datenbanken offset
Werte verarbeiten, wird die offsetbasierte Pagination mit zunehmendem Seitenzahl weniger effizient. Dies liegt daran, dass die Datenbank bei Verwendung eines Offsets immer noch alle Datensätze bis zum Offset -Wert durchsuchen muss. Sie werden nur verworfen und in den Abfrageberichten nicht zurückgegeben.
Hier ist ein großartiger Artikel, in dem dies genauer erklärt: https://use-the-index-luke.com/no-cret.
Wenn die Gesamtmenge der Daten in der Datenbank wächst und die Seitenzahl zunimmt, kann die offsetbasierte Pagination weniger effizient werden. In diesen Fällen ist die Cursor-basierte Pagination leistungsfähiger, insbesondere wenn das Cursorfeld indiziert ist, da die vorherigen Datensätze nicht gelesen werden. Wenn Sie eine Paginierung gegen einen großen Datensatz verwenden, möchten Sie sich möglicherweise für die Cursorpagination über die Offset -Pagination entscheiden.
Offset-basierte Pagination kann unter Problemen leiden, wenn der zugrunde liegende Datensatz zwischen Anforderungen ändert.
Schauen wir uns ein Beispiel an.
Nehmen wir an, wir haben die folgenden 10 Benutzer in unserer Datenbank:
Wir stellen eine Anfrage zum Abrufen der ersten Seite (5 Benutzer) und die folgenden Benutzer abrufen:
Wenn wir zu Seite 2 navigieren, erwarten wir die Benutzer von 6 bis 10. Stellen wir uns jedoch vor, dass Benutzer 1 aus der Datenbank gelöscht wird, bevor wir Seite 2 laden (während wir noch Seite 1 anzeigen). Da die Seitengröße 5 ist, würde die Abfrage zum Abrufen der nächsten Seite so aussehen:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
Dies bedeutet, dass wir die ersten 5 Datensätze überspringen und die nächsten abrufen 5.
Dies würde dazu führen, dass Seite 2 die folgenden Benutzer enthalten:
Wie wir sehen, fehlt Benutzer 6 in der Liste. Dies liegt daran, dass Benutzer 6 jetzt der 5. Datensatz in der Tabelle ist, also sind sie tatsächlich auf der ersten Seite.
Cursor-basierter Pagination hat dieses Problem nicht, da wir keine Datensätze überspringen. Wir holen nur den nächsten Satz von Datensätzen, die auf einem Cursor basieren. Stellen wir uns vor, wir hatten im obigen Beispiel Cursor-basierte Pagination verwendet. Der Cursor für Seite 2 wäre die ID von Benutzer 5 (von dem wir annehmen, dass er 5 ist), da es der letzte Datensatz auf der ersten Seite war. Unsere Abfrage für Seite 2 kann also so aussehen:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
Ausführen der obigen Abfrage würde die Benutzer wie erwartet 6 bis 10 zurückgeben.
Dies sollte hoffentlich hervorheben, wie eine packungsbasierte Pagination problematisch werden kann, wenn die zugrunde liegenden Daten geändert, hinzugefügt oder entfernt werden, während sie gelesen werden. Es wird weniger vorhersehbar und kann zu unerwarteten Ergebnissen führen.
Es ist wichtig, sich daran zu erinnern, dass Sie nicht auf eine einzelne Art von Pagination in Ihrer Anwendung befestigt sind. An einigen Stellen kann die Offset -Pagination besser geeignet sein (möglicherweise für UI -Zwecke), und in anderen kann die Cursorpagination effizienter sein (z. B. bei der Arbeit mit einem großen Datensatz). So können Sie je nach Anwendungsfall Paginationsmethoden in Ihrer Anwendung mischen und anpassen.
Wenn Sie jedoch eine API bauen, würde ich Ihnen sehr empfehlen, dass Sie konsistent sind und einen einzelnen Paginationsansatz für alle Ihre Endpunkte verwenden. Dies erleichtert Entwicklern zu verstehen, wie Sie Ihre API verwenden und Verwirrung vermeiden können.
Sie möchten nicht, dass sie sich daran erinnern müssen, welche Endpunkte die Offset-Pagination verwenden und welche Cursor-Pagination verwenden.
Dies ist natürlich keine harte und schnelle Regel. Wenn Sie wirklich eine andere Paginierungsmethode in einem bestimmten Endpunkt verwenden müssen, dann fahren Sie fort. Stellen Sie jedoch nur sicher, dass Sie in der Dokumentation klar machen, dass Entwickler das Verständnis erleichtert.
Wenn Sie eher ein visueller Lerner sind, sollten Sie sich dieses großartige Video von Aaron Francis ansehen, das den Unterschied zwischen Offset- und Cursor-basierter Pagination ausführlicher erklärt:
In diesem Artikel haben wir uns die verschiedenen Arten der Pagination in Laravel und in der Art und Weise angesehen, wie sie verwendet werden. Wir haben uns auch ihre zugrunde liegenden SQL -Abfragen angesehen und wie man entscheidet, welche Pagination in Ihrer Anwendung verwendet werden soll.
Hoffentlich sollten Sie sich jetzt sicherer fühlen, wenn Sie Paginierung in Ihren Laravel -Anwendungen verwenden.
Das obige ist der detaillierte Inhalt vonEin Leitfaden zur Paginierung in Laravel. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!