Pagination adalah ciri umum dalam aplikasi web. Hampir setiap aplikasi Laravel yang pernah saya kerjakan mempunyai beberapa bentuk penomboran yang dilaksanakan.
Tetapi apakah penomboran dan mengapa kita menggunakannya? Bagaimanakah kita dapat melaksanakan penomboran dalam aplikasi Laravel kita? Dan bagaimana kita menentukan kaedah penomboran mana yang hendak digunakan?
Dalam artikel ini, kami akan menjawab soalan -soalan yang sangat dan meneroka cara menggunakan penomboran di Laravel untuk kedua -dua pandangan bilah dan titik akhir API. Menjelang akhir artikel ini, anda harus merasa cukup yakin untuk mula menggunakan penomboran dalam projek anda sendiri.
Pagination adalah teknik yang digunakan untuk membahagikan dataset besar ke dalam ketulan yang lebih kecil (atau halaman). Ia membolehkan anda memaparkan subset data, dan bukannya semua nilai yang mungkin sekaligus.
Sebagai contoh, bayangkan anda mempunyai halaman yang mengeluarkan nama semua pengguna dalam aplikasi anda. Jika anda mempunyai beribu -ribu pengguna, tidak akan praktikal untuk memaparkan semuanya pada satu halaman. Sebaliknya, anda boleh menggunakan penomboran untuk memaparkan subset pengguna (katakan 10 pengguna pada satu masa) pada setiap halaman, dan membolehkan pengguna menavigasi antara halaman untuk melihat lebih banyak pengguna (10 seterusnya).
dengan menggunakan penomboran anda boleh:
paginate
- Menggunakan penomboran berasaskan offset dan mengambil jumlah rekod dalam dataset. simplePaginate
- Menggunakan penomboran berasaskan offset tetapi tidak mengambil jumlah rekod dalam dataset. cursorPaginate
- Menggunakan penomboran berasaskan kursor dan tidak mengambil jumlah rekod dalam dataset. mari kita lihat setiap kaedah ini dengan lebih terperinci.
paginate
Kaedah paginate
membolehkan anda mengambil subset data dari pangkalan data berdasarkan offset dan had (kita akan melihatnya kemudian apabila kita melihat pertanyaan SQL yang mendasari).
anda boleh menggunakan kaedah paginate
seperti:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
yang menjalankan kod di atas akan menghasilkan $users
sebagai contoh IlluminateContractsPaginationLengthAwarePaginator
, biasanya objek IlluminatePaginationLengthAwarePaginator
. Contoh Paginator ini mengandungi semua maklumat yang anda perlukan untuk memaparkan data paginated dalam aplikasi anda.
Kaedah paginate
secara automatik boleh menentukan nombor halaman yang diminta berdasarkan parameter pertanyaan page
dalam URL. Sebagai contoh, jika anda melawat https://my-app.com/users?page=2
, kaedah paginate
akan mengambil halaman kedua data.
Secara lalai, semua kaedah penomboran dalam lalai Laravel untuk mengambil 15 rekod pada satu masa. Walau bagaimanapun, ini boleh ditukar kepada nilai yang berbeza (kita akan melihat bagaimana untuk melakukannya kemudian).
paginate
dengan pandangan bilah mari kita lihat cara menggunakan kaedah paginate
apabila memberikan data dalam pandangan bilah.
Bayangkan kita mempunyai laluan mudah yang mengambil pengguna dari pangkalan data dalam format paginated dan menyampaikannya kepada pandangan:
<!-- 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, ]); });
fail resources/views/users/index.blade.php
kami mungkin kelihatan seperti ini:
<!-- 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>
Halaman yang dihasilkan akan kelihatan seperti ini:
mari kita pecahkan apa yang berlaku dalam pandangan bilah:
$users
(objek IlluminatePaginationLengthAwarePaginator
) dan mengeluarkan nama mereka. links
pada objek $users
. Ini adalah kaedah yang sangat berguna yang mengembalikan beberapa HTML yang memaparkan pautan penomboran (mis., "Sebelumnya", "Seterusnya", dan nombor halaman). Ini bermakna anda tidak perlu risau tentang membuat pautan penomboran sendiri, dan Laravel akan mengendalikan semua itu untuk anda. kita juga dapat melihat bahawa kaedah paginate
memberi kita gambaran keseluruhan data penomboran. Kita dapat melihat bahawa kita melihat rekod ke -16 hingga ke -30, daripada 50 rekod. Kita juga dapat melihat bahawa kita berada di halaman kedua dan terdapat sejumlah 4 halaman.
Penting untuk diperhatikan bahawa kaedah links
akan mengembalikan gaya HTML menggunakan CSS Tailwind. Jika anda ingin menggunakan sesuatu selain daripada Tailwind atau anda ingin gaya penomboran pautan sendiri, anda boleh menyemak dokumentasi untuk menyesuaikan pandangan penomboran.
paginate
di titik akhir API Serta menggunakan kaedah paginate
dalam pandangan bilah, anda juga boleh menggunakannya dalam titik akhir API. Laravel menjadikan proses ini mudah dengan menukarkan data paginat secara automatik ke JSON.
(dengan menambahkan laluan berikut ke fail /api/users
kami) yang mengembalikan pengguna paginated dalam format JSON: routes/api.php
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
akan mengembalikan respons JSON yang serupa dengan yang berikut (sila ambil perhatian saya telah mengehadkan medan /api/users
kepada hanya 3 rekod demi keringkasan): data
<!-- 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, ]); });
current_page
- Halaman semasa yang kita sedang aktif. Dalam kes ini, kami berada di halaman pertama. data
- Data sebenar itu sendiri yang dikembalikan. Dalam kes ini, ia mengandungi 15 pengguna pertama (dipendekkan hingga 3 untuk keringkasan). first_page_url
- URL ke halaman pertama data. from
- Nombor rekod permulaan data yang dikembalikan. Dalam kes ini, ia adalah rekod pertama. Sekiranya kami berada di halaman kedua, ini akan menjadi 16. last_page
- Jumlah halaman data. Dalam kes ini, terdapat 4 halaman. last_page_url
- URL ke halaman terakhir data. links
- pelbagai pautan ke halaman data yang berbeza. Ini termasuk pautan "sebelumnya" dan "seterusnya", serta nombor halaman. next_page_url
- URL ke halaman data seterusnya. path
- URL asas titik akhir. per_page
- Bilangan rekod yang dikembalikan setiap halaman. Dalam kes ini, ia adalah 15. prev_page_url
- URL ke halaman data sebelumnya. Dalam kes ini, ia null
kerana kita berada di halaman pertama. Jika kami berada di halaman kedua, ini akan menjadi URL ke halaman pertama. to
- Nombor rekod akhir data yang dikembalikan. Dalam kes ini, ia adalah rekod ke -15. Sekiranya kami berada di halaman kedua, ini akan menjadi 30. total
- Jumlah rekod dalam dataset. Dalam kes ini, terdapat 50 rekod. menggunakan kaedah paginate
dalam Laravel hasil dalam dua pertanyaan SQL yang dijalankan:
Jadi jika kita mahu mengambil halaman pertama pengguna (dengan 15 pengguna setiap halaman), pertanyaan SQL berikut akan dijalankan:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
dan
<!-- 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, ]); });
Dalam pertanyaan kedua, kita dapat melihat bahawa nilai limit
ditetapkan kepada 15. Ini adalah bilangan rekod yang dikembalikan setiap halaman.
nilai offset
<!-- 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>
akan dikira sebagai: offset
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('paginate', function () { return User::query()->paginate(); });
offset
<!-- 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 }
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
simplePaginate
kaedah simplePaginate
sangat serupa dengan kaedah paginate
tetapi dengan satu perbezaan utama. Kaedah simplePaginate
tidak mengambil jumlah rekod dalam dataset.
Seperti yang telah kita lihat, apabila kita menggunakan kaedah paginate
, kita juga mendapat maklumat mengenai jumlah rekod dan halaman yang terdapat dalam dataset. Kami kemudian boleh menggunakan maklumat ini untuk memaparkan perkara seperti jumlah halaman dalam respons UI atau API.
Tetapi jika anda tidak berhasrat untuk memaparkan butiran ini kepada pengguna (atau pemaju yang memakan API), maka kita boleh mengelakkan pertanyaan pangkalan data yang tidak diperlukan (yang mengira jumlah rekod) dengan menggunakan kaedah simplePaginate
.
kaedah simplePaginate
boleh digunakan dengan cara yang sama seperti paginate
kaedah:
<!-- 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, ]); });
menjalankan kod di atas akan menghasilkan $users
sebagai contoh IlluminateContractsPaginationPaginator
, biasanya objek IlluminatePaginationPaginator
.
Tidak seperti objek IlluminatePaginationLengthAwarePaginator
yang dikembalikan oleh kaedah paginate
, objek IlluminatePaginationPaginator
tidak mengandungi maklumat mengenai jumlah rekod dalam dataset dan tidak tahu berapa banyak halaman atau jumlah rekod yang ada. Ia hanya tahu mengenai halaman data semasa dan sama ada terdapat lebih banyak rekod untuk diambil.
simplePaginate
dengan pandangan bilah mari kita lihat bagaimana anda boleh menggunakan kaedah simplePaginate
dengan paparan bilah. Kami akan menganggap kami mempunyai laluan yang sama seperti sebelumnya, tetapi kali ini kami menggunakan kaedah simplePaginate
:
<!-- 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>
kami akan membina pandangan bilah kami dengan cara yang sama seperti sebelumnya:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('paginate', function () { return User::query()->paginate(); });
Halaman yang dihasilkan akan kelihatan seperti ini:
Seperti yang dapat kita lihat dalam contoh ini, output $users->links()
adalah berbeza dengan output yang kita lihat ketika menggunakan kaedah paginate
. Oleh kerana kaedah simplePaginate
tidak mengambil jumlah rekod, ia tidak mempunyai konteks jumlah halaman atau rekod, hanya sama ada terdapat halaman seterusnya atau tidak. Oleh itu, kita hanya melihat pautan "sebelumnya" dan "seterusnya" dalam pautan penomboran.
simplePaginate
di titik akhir API anda juga boleh menggunakan kaedah simplePaginate
dalam titik akhir API. Laravel secara automatik akan menukar data paginated ke JSON untuk anda.
mari kita membina titik akhir /api/users
yang mengembalikan pengguna paginated dalam format json:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
Apabila kita memukul laluan ini, kita akan mendapat respons JSON yang serupa dengan yang berikut (saya telah mengehadkan medan data
kepada hanya 3 rekod untuk keringkasan):
<!-- 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, ]); });
Seperti yang dapat kita lihat, tindak balas JSON sangat mirip dengan tindak balas yang kita dapat ketika menggunakan kaedah paginate
. Perbezaan utama ialah kita tidak mempunyai medan last_page
, last_page_url
, links
, atau total
dalam respons.
mari kita lihat pertanyaan SQL yang mendasari yang dijalankan semasa menggunakan kaedah simplePaginate
.
kaedah simplePaginate
masih bergantung pada nilai limit
dan offset
untuk mengambil subset data dari pangkalan data. Walau bagaimanapun, ia tidak menjalankan pertanyaan untuk mengambil jumlah rekod dalam dataset.
nilai offset
<!-- 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>
. Ia dikira sebagai: limit
paginate
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('paginate', function () { return User::query()->paginate(); });
untuk menentukan sama ada terdapat lebih banyak rekod untuk diambil. Sebagai contoh, katakan kami mengambil 15 rekod setiap halaman. Nilai simplePaginate
akan menjadi 16. Jadi jika 16 rekod dikembalikan, kami akan tahu terdapat sekurang -kurangnya satu lagi halaman data yang tersedia untuk diambil. Sekiranya kurang daripada 16 rekod telah dikembalikan, kami akan tahu bahawa kami berada di halaman terakhir data. perPage
limit
Jadi jika kita mahu mengambil halaman pertama pengguna (dengan 15 pengguna setiap halaman), pertanyaan SQL berikut akan dijalankan:
pertanyaan untuk halaman kedua akan kelihatan seperti:
<!-- 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 }
#menggunakan kaedah
<!-- Syntax highlighted by torchlight.dev -->select count(*) as aggregate from `users`
cursorPaginate
Setakat ini kami telah melihat kaedah yang kedua-duanya menggunakan penomboran berasaskan offset. Kami kini akan melihat kaedah paginate
yang menggunakan penomboran berasaskan kursor. simplePaginate
cursorPaginate
Sebagai penomboran berasaskan kursor, mungkin kelihatan sedikit mengelirukan pada kali pertama anda melihatnya. Oleh itu, jangan risau jika anda tidak dapat mendapatkannya dengan segera. Mudah -mudahan, pada akhir artikel ini, anda akan mempunyai pemahaman yang lebih baik tentang bagaimana ia berfungsi. Saya juga akan meninggalkan video yang hebat di hujung artikel ini yang menerangkan penomboran berasaskan kursor dengan lebih terperinci.
dan
untuk mengambil subset data dari pangkalan data. Jadi kita boleh mengatakan "Langkau 10 rekod pertama dan ambil 10 rekod seterusnya". Ini mudah difahami dan mudah dilaksanakan. Sedangkan dengan penomboran kursor, kami menggunakan kursor (biasanya pengenal unik untuk rekod tertentu dalam pangkalan data) sebagai titik permulaan untuk mengambil set rekod sebelumnya/seterusnya.Sebagai contoh, katakan kami membuat pertanyaan untuk mengambil 15 pengguna pertama. Kami akan menganggap ID pengguna ke -15 adalah 20. Apabila kami ingin mengambil 15 pengguna seterusnya, kami akan menggunakan ID pengguna ke -15 (20) sebagai kursor. Kami akan mengatakan "Ambil 15 pengguna seterusnya dengan ID lebih besar daripada 20".
Anda kadang -kadang boleh melihat kursor yang dirujuk sebagai "token", "kunci", "seterusnya", "sebelumnya", dan sebagainya. Mereka pada dasarnya merujuk kepada rekod tertentu dalam pangkalan data. Kami akan melihat struktur kursor kemudian dalam bahagian ini apabila kita melihat pertanyaan SQL yang mendasari.
Laravel membolehkan kita menggunakan penomboran berasaskan kursor dengan kaedah cursorPaginate
:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
yang menjalankan kod di atas akan mengakibatkan medan $users
menjadi contoh IlluminateContractsPaginationCursorPaginator
, biasanya objek IlluminatePaginationCursorPaginator
. Contoh Paginator ini mengandungi semua maklumat yang anda perlukan untuk memaparkan data paginated dalam aplikasi anda.
Sama seperti kaedah simplePaginate
, kaedah cursorPaginate
tidak mengambil jumlah rekod dalam dataset. Ia hanya mengetahui tentang halaman data semasa dan sama ada terdapat lebih banyak rekod untuk diambil, jadi kami tidak menyedari jumlah halaman atau rekod dengan segera.
cursorPaginate
dengan pandangan bilah Mari kita lihat cara menggunakan kaedah cursorPaginate
apabila memberikan data dalam paparan bilah. Sama seperti contoh terdahulu kami, kami akan menganggap kami mempunyai laluan mudah yang mengambil pengguna dari pangkalan data dalam format paginated dan menyampaikannya kepada pandangan:
<!-- 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, ]); });
pandangan bilah mungkin kelihatan seperti ini:
<!-- 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>
Ini akan mengeluarkan halaman yang serupa dengan yang berikut:
Seperti yang dapat kita lihat, kerana kaedah cursorPaginate
tidak mengambil jumlah rekod dalam dataset, output $users->links()
adalah serupa dengan output yang kita lihat apabila menggunakan kaedah simplePaginate
. Kami hanya melihat pautan "sebelumnya" dan "seterusnya" dalam pautan penomboran.
cursorPaginate
di titik akhir API Laravel juga membolehkan anda menggunakan kaedah cursorPaginate
dalam titik akhir API dan secara automatik akan menukar data paginated ke JSON untuk kami.
mari kita membina titik akhir /api/users
yang mengembalikan pengguna paginated dalam format json:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('paginate', function () { return User::query()->paginate(); });
Apabila kita memukul laluan ini, kita akan mendapat respons JSON yang serupa dengan yang berikut (saya telah mengehadkan medan data
kepada hanya 3 rekod untuk keringkasan):
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
Seperti yang dapat kita lihat, tindak balas JSON adalah serupa dengan respons terdahulu yang telah kita lihat tetapi dengan beberapa perbezaan kecil. Oleh kerana kita tidak mengambil jumlah rekod, kita tidak mempunyai medan last_page
, last_page_url
, links
, atau total
dalam respons. Anda juga mungkin menyedari bahawa kami tidak mempunyai medan from
dan to
sama ada.
Sebaliknya, kita mempunyai medan next_cursor
dan prev_cursor
yang mengandungi kursor untuk halaman data seterusnya dan sebelumnya. Oleh kerana kita berada di halaman pertama, medan prev_cursor
dan prev_page_url
kedua -duanya null
. Walau bagaimanapun, medan next_cursor
dan next_page_url
ditetapkan.
medan next_cursor
adalah rentetan asas-64 yang mengandungi kursor untuk halaman data seterusnya. Sekiranya kita menyahkod medan next_cursor
, kita akan mendapat sesuatu seperti ini (dicantikkan untuk kebolehbacaan):
<!-- 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, ]); });
kursor mengandungi dua maklumat berasingan:
users.id
- ID rekod terakhir yang diambil dalam dataset. _pointsToNextItems
- Nilai boolean yang memberitahu kami sama ada kursor menunjuk kepada set item seterusnya atau sebelumnya. Jika nilai itu true
ia bermakna kursor harus digunakan untuk mengambil set rekod seterusnya dengan ID lebih besar daripada nilai users.id
. Sekiranya nilai itu false
, ini bermakna kursor harus digunakan untuk mengambil set rekod sebelumnya dengan ID kurang daripada nilai users.id
. mari kita lihat pada halaman kedua data yang kelihatan seperti (sekali lagi, dipendekkan kepada 3 rekod untuk keringkasan):
<!-- 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>
kita dapat melihat bahawa medan prev_cursor
dan prev_page_url
kini ditetapkan, dan medan next_cursor
dan next_page_url
telah dikemas kini dengan kursor untuk halaman seterusnya.
.
cursorPaginate
Pada halaman pertama data (mengandungi 15 rekod), pertanyaan SQL berikut akan dijalankan:
kita dapat melihat bahawa kita mengambil 16 rekod pertama dari jadual
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('paginate', function () { return User::query()->paginate(); });
dalam urutan menaik. Sama dengan kaedah users
, kami mengambil 16 baris kerana kami ingin menentukan sama ada terdapat lebih banyak rekod untuk diambil. id
simplePaginate
Bayangkan kita kemudian menavigasi ke halaman seterusnya item dengan kursor berikut:
Apabila kursor ini dimulakan, kami mendapat objek JSON berikut:
<!-- 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 kemudian akan menjalankan pertanyaan SQL berikut untuk mengambil set rekod seterusnya:
<!-- Syntax highlighted by torchlight.dev -->select count(*) as aggregate from `users`
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
Seperti yang dapat kita lihat, kita mengambil 16 rekod seterusnya dari jadual users
yang mempunyai id
lebih besar daripada 15 (sejak 15 adalah ID terakhir pada halaman sebelumnya).
Sekarang mari kita anggap bahawa ID pengguna pertama pada halaman 2 adalah 16. Apabila kita menavigasi kembali ke halaman pertama data dari halaman kedua, kursor berikut akan digunakan:
<!-- 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, ]); });
Apabila ini dimulakan, kami mendapat objek JSON berikut:
<!-- 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>
Apabila kita bergerak ke halaman seterusnya hasil, rekod terakhir yang diambil digunakan sebagai kursor. Apabila kita kembali ke halaman keputusan sebelumnya, rekod pertama diambil digunakan sebagai kursor. Atas sebab ini, kita dapat melihat nilai users.id
ditetapkan kepada 16 dalam kursor. Kita juga dapat melihat bahawa nilai _pointsToNextItems
ditetapkan ke false
kerana kita kembali ke set item sebelumnya.
Akibatnya, pertanyaan SQL berikut akan dijalankan untuk mengambil set rekod sebelumnya:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; use Illuminate\Support\Facades\Route; Route::get('paginate', function () { return User::query()->paginate(); });
seperti yang dapat kita lihat, kekangan where
kini memeriksa rekod dengan id
kurang daripada 16 (sejak 16 adalah ID pertama pada halaman 2) dan hasilnya diperintahkan dalam urutan menurun.
Setakat ini, dalam contoh API kami, kami baru saja mengembalikan data paginated secara langsung dari pengawal. Walau bagaimanapun, dalam aplikasi dunia sebenar, anda mungkin mahu memproses data sebelum mengembalikannya kepada pengguna. Ini boleh jadi apa -apa daripada menambah atau mengeluarkan medan, menukar jenis data, atau bahkan mengubah data ke dalam format yang berbeza sama sekali. Atas sebab ini, anda mungkin mahu menggunakan sumber API kerana mereka menyediakan cara untuk anda secara konsisten mengubah data anda sebelum mengembalikannya.
Laravel membolehkan anda menggunakan sumber API bersama penomboran. Mari kita lihat contoh bagaimana untuk melakukan ini.
Bayangkan kami telah mencipta kelas sumber API yang mengubah data pengguna sebelum mengembalikannya. Ia mungkin kelihatan seperti ini: AppHttpResourcesUserResource
<!-- 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 }
, kami menentukan bahawa setiap kali kami memproses pengguna melalui sumber ini, kami hanya ingin mengembalikan bidang toArray
, id
, dan name
.
email
Sekarang mari kita membina titik akhir API
kami yang mengembalikan pengguna paginated menggunakan /api/users
: routes/api.php
AppHttpResourcesUserResource
<!-- Syntax highlighted by torchlight.dev -->select count(*) as aggregate from `users`
) ke kaedah $users
. Kaedah ini akan mengubah data paginated menggunakan IlluminatePaginationLengthAwarePaginator
sebelum mengembalikannya kepada pengguna. UserResource::collection
Apabila kita memukul titik akhir /api/users
, kita akan mendapat respons JSON yang serupa dengan yang berikut (saya telah mengehadkan medan data
kepada hanya 3 rekod untuk keringkasan):
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
Seperti yang dapat kita lihat di JSON di atas, Laravel mengesan bahawa kita sedang bekerja dengan dataset paginated dan mengembalikan data paginated dalam format yang sama seperti sebelumnya. Walau bagaimanapun, kali ini pengguna dalam medan data
hanya mengandungi medan id
, name
, dan email
yang kami tentukan dalam kelas sumber API kami. Bidang lain (current_page
, from
, last_page
, links
, path
, dan per_page
) masih dikembalikan kerana mereka adalah sebahagian daripada data paginated, tetapi mereka telah diletakkan di dalam medan to
. Terdapat juga medan total
yang mengandungi meta
, links
, first
, dan last
pautan ke halaman data yang berbeza. prev
next
#changing nilai per halaman
Laravel menjadikannya mudah untuk menukar bilangan rekod yang dipaparkan setiap halaman dengan lulus parameter
ke kaedah, perPage
, dan simplePaginate
. Parameter ini membolehkan anda menentukan bilangan rekod yang ingin anda paparkan setiap halaman. paginate
cursorPaginate
mari kita lihat contoh mudah bagaimana membaca parameter pertanyaan
per_page
<!-- 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, ]); });
kaedah per_page
. perPage
paginate
kita kemudian dapat mengakses URL yang berbeza ini:
https://my-app.com/users
https://my-app.com/users?per_page=5
https://my-app.com/users?per_page=5&page=2
dan sebagainya ... Jika anda membina titik akhir UI atau API yang memerlukan jumlah rekod atau halaman yang akan dipaparkan, maka kaedah
Jika anda tidak memerlukan salah satu daripada ini, maka simplePaginate
atau cursorPaginate
akan lebih efisien kerana mereka tidak melakukan pertanyaan yang tidak perlu untuk mengira jumlah rekod.
Jika anda perlu melompat ke halaman data tertentu, maka penomboran berasaskan mengimbangi lebih sesuai. Oleh kerana penomboran kursor adalah negara, ia bergantung pada halaman sebelumnya untuk mengetahui ke mana hendak pergi seterusnya. Oleh itu, ia tidak semudah melompat ke halaman tertentu.
Manakala apabila menggunakan penomboran offset, anda biasanya boleh lulus nombor halaman dalam permintaan (mungkin sebagai parameter pertanyaan) dan melompat ke halaman itu tanpa mempunyai konteks halaman sebelumnya.
Oleh kerana cara pangkalan data mengendalikan offset
nilai, penomboran berasaskan offset menjadi kurang efisien apabila nombor halaman meningkat. Ini kerana apabila anda menggunakan offset, pangkalan data masih perlu mengimbas semua rekod sehingga nilai offset. Mereka hanya dibuang dan tidak dikembalikan dalam hasil pertanyaan.
Inilah artikel hebat yang menerangkan ini dengan lebih terperinci: https://use-the-index-luke.com/no-offset.
Oleh kerana jumlah data dalam pangkalan data berkembang dan nombor halaman meningkat, penomboran berasaskan mengimbangi dapat menjadi kurang efisien. Dalam kes ini, penomboran berasaskan kursor lebih banyak, terutamanya jika medan kursor diindeks, kerana rekod sebelumnya tidak dibaca. Atas sebab ini, jika anda akan menggunakan penomboran terhadap dataset yang besar, anda mungkin mahu memilih penomboran kursor atas penomboran mengimbangi.
penomboran berasaskan offset boleh mengalami masalah jika dataset asas berubah antara permintaan.
mari kita lihat contoh.
katakan kami mempunyai 10 pengguna berikut dalam pangkalan data kami:
kami membuat permintaan untuk mengambil halaman pertama (mengandungi 5 pengguna) dan dapatkan pengguna berikut:
Apabila kami menavigasi ke halaman 2, kami mengharapkan untuk mendapatkan pengguna 6 hingga 10. Namun, bayangkan bahawa sebelum kami memuatkan halaman 2 (sementara kami masih melihat halaman 1), pengguna 1 dipadam dari pangkalan data. Oleh kerana saiz halaman adalah 5, pertanyaan untuk mengambil halaman seterusnya akan kelihatan seperti ini:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
ini bermakna kita melangkau 5 rekod pertama dan mengambil 5.
seterusnyaIni akan menghasilkan halaman 2 yang mengandungi pengguna berikut:
Seperti yang dapat kita lihat, pengguna 6 hilang dari senarai. Ini kerana pengguna 6 kini merupakan rekod ke -5 dalam jadual, jadi mereka sebenarnya berada di halaman pertama.
Pagination berasaskan kursor tidak mempunyai masalah ini, kerana kami tidak melangkau rekod, kami hanya mengambil set rekod seterusnya berdasarkan kursor. Mari kita bayangkan kami menggunakan penomboran berasaskan kursor dalam contoh di atas. Kursor untuk halaman 2 akan menjadi ID Pengguna 5 (yang akan kita anggap adalah 5) kerana ia adalah rekod terakhir pada halaman pertama. Jadi pertanyaan kami untuk halaman 2 mungkin kelihatan seperti ini:
<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate();
Menjalankan pertanyaan di atas akan mengembalikan pengguna 6 hingga 10 seperti yang diharapkan.
Ini semestinya menyerlahkan bagaimana penomboran berasaskan offset boleh menjadi bermasalah apabila data mendasar ditukar, ditambah, atau dikeluarkan semasa dibaca. Ia menjadi kurang diramalkan dan boleh menyebabkan hasil yang tidak dijangka.
Penting untuk diingat bahawa anda tidak tetap menggunakan satu jenis penomboran dalam aplikasi anda. Di sesetengah tempat, penomboran mengimbangi mungkin lebih sesuai (mungkin untuk tujuan UI) dan pada yang lain, penomboran kursor mungkin lebih cekap (seperti ketika bekerja dengan dataset yang besar). Oleh itu, anda boleh mencampur dan memadankan kaedah penomboran dalam aplikasi anda bergantung pada kes penggunaan.
anda tidak mahu mereka perlu ingat titik akhir yang menggunakan penukaran offset dan yang menggunakan paginasi kursor.
Sudah tentu, ini bukan peraturan yang keras dan cepat. Jika anda benar -benar perlu menggunakan kaedah penomboran yang berbeza dalam satu titik akhir tertentu, maka teruskan. Tetapi pastikan untuk menjelaskan dengan jelas dalam dokumentasi untuk memudahkan pemaju memahami.
#prefer video sebaliknya?
#conclusion
Mudah -mudahan, anda kini harus merasa lebih yakin menggunakan penomboran dalam aplikasi Laravel anda.
Atas ialah kandungan terperinci Panduan untuk Penomboran di Laravel. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!