Di beberapa framework PHP lain, membuat pagination itu kadang sungguh merepotkan. Kita harus menghitung jumlah datanya terlebih dahulu, mengatur offset/index data, mengatur jumlah per halaman, kemudian menggunakan pengaturan tadi pada class pagination. Belum selesai sampai di situ, kita tambah direpotkan karena harus membuat sendiri tampilan untuk pagination-nya.
- Membuat Fitur Search + Pagination
- Membuat Pagination Secara Manual
- Pagination di Laravel itu Mudah!
- Membuat Navigasi Sederhana (Kasus: Next & Prev)
Di Laravel, membuat pagination jauh lebih mudah karena sudah terintegrasi dengan DB Builder dan Eloquent. Kalian cukup menggunakan method paginate()
pada saat query data, data pagination sudah siap digunakan. Selain itu, tampilan pun secara bawaan sudah tersedia dengan basis Bootstrap CSS Framework.
Dalam instalasi Laravel, sudah tersedia migration untuk tabelusers
. Dengan asumsi kalian sudah menjalankan migration tersebut, dan mengisi data untuk tabelusers
dengan jumlah lebih dari lebih dari 100.
***
Karena datanya masih sedikit, saya rasa menampilkan langsung semua data tersebut pada satu halaman sah-sah saja dilakukan. Lain cerita kalau jumlah datanya sudah jutaan, maka performa query akan sangat kelihatan di sini, proses jadi lebih lambat. Lagian, secara experience, pengguna merasa tidak begitu nyaman membaca data yang jumlahnya ratusan ditumpuk dalam satu halaman.
Daftar Isi
Contoh Penggunaan (DB Builder)
Sebelumnya, saya punya potongan skrip di bawah untuk menampilkan data users
:
public function index() : \Illuminate\View\View { $users = \DB::table('users')->get(); return view('user.index', compact('users')); }
Dengan melakukan perulangan (looping) pada variabel $users
, kita bisa menampilkan semua datausers
pada view dengan Blade directive.
// menampilkan data di view @foreach ($users as $user) {{ $user->name }} @endforeach
Untuk menjadikan data users
menjadi beberapa bagian dalam bentuk halaman (pagination), kita bisa mengganti method get()
menjadi method paginate()
.
public function index() : \Illuminate\View\View { $users = \DB::table('users')->paginate(); return view('user.index', compact('users')); }
Pengulangan variabel $users
tetap menghasilkan data yang sama seperti skrip di sebelumnya, hanya saja jumlah datanya ditampilkan terbatas yang secara bawaan jumlahnya adalah 15 baris (rows).
Untuk menampilkan nomor halaman beserta tautannya, kalian cukup menambahkan potongan skrip di bawah pada view dari variabel $users
.
$users->links();
Maka, tautan pagination akan dibuat dan diatur secara otomatis.
Ketika menggunakan method
paginate()
, maka variabel$user
merupakan instance pagination, bukan instance DB Builder atau Eloquent.
Integrasi dengan Eloquent
Tak hanya DB Builder, pagination juga mendukung query menggunakan Eloquent. Sebagai contoh, untuk menampilkan semua datausers
, kita bisa menggunakan skrip di bawah.
$users = App\User::all(); // atau $users = App\User::get();
Untuk memecah data users menjadi beberapa halaman dalam pagination, kalian bisa mengganti method all()
atau get()
dengan paginate()
.
$users = App\User::paginate();
Untuk menampilkan data dan tautan pagination (beserta nomor halaman), caranya sama dengan cara di atas, yaitu menggunakan method links()
dari variabel $users
.
Method “simplePaginate”
Selain method paginate()
, dalam pagination juga terdapat method simplePaginate()
. Bedanya, jika paginate()
akan menampilkan nomor halaman pada tautan, maka simplePaginate()
hanya menampilkan navigasi “next” dan “prev” saja.
$users = App\User::simplePaginate();
Bagusnya, penggunaan simplePaginate()
memberikan query yang lebih efesien sehingga meningkatkan performa aplikasi.
Di samping itu, penggunaan method simplepaPaginate()
juga memberikan efek samping lain. Beberapa method dari instance class pagination tidak dapat digunakan. Baca selengkapnya pada sub-topik Method dalam Pagination.
Jumlah Data
Secara bawaan, data yang ditampilkan per halaman jumlahnya adalah 15. Kita sebagai pengembang aplikasi tentu saja diberikan kebebasan untuk menentukan jumlah data per halaman.
Untuk menentukan jumlah data per halaman, kita bisa melempar argumen pertama pada method paginate dengan tipe data integer. Sebagai contoh:
$users = \App\User::paginate(50);
Skrip di atas berefek menampilkan 50 datausers
per halaman.
Menampilkan dalam Bentuk JSON
Menampilkan data + pagination cukup mudah. Alih-alih menggunakan method view()
untuk memuat tampilkan, kalian bisa menampilkannya langsung dengan classJsonResponse
menggunakan method json()
.
public function index(): \Illuminate\Response\JsonResponse { $users = App\User::paginate(); return response()->json($users); }
Potongan skrip di atas otomatis menghasilkan data dalam format JSON dengan struktur datanya seperti di bawah:
{ "total": 50, "per_page": 15, "current_page": 1, "last_page": 4, "next_page_url": "http://laravel.app?page=2", "prev_page_url": null, "from": 1, "to": 15, "data":[ { // Result Object }, { // Result Object } ] }
Custom Path
Laravel menggunakan current path untuk menentukan base path pagination pada saat di-generate.
Contoh kasus: untuk menampilkan data user, kita menggunakan path user. Pada saat pagination di-generate, maka path user akan digunakan juga pada halaman-halaman berikutnya menjadi: user?page=1
, dan seterusnya.
Lantas, bagaimana seandainya kita menampilkan pagination di path dashboard, tapi pagination sesungguhnya ada di path user? Untuk menangani kasus ini, kita bisa menggunakan method withPath()
.
$users = \App\Users::paginate(20); // set default path $users->withPath('users');
Menambahkan Query String pada URL
Menuju kasus yang sedikit lebih rumit. Ambil contoh kalian akan membuat fitur pencarian + pagination. Yang mana, jika query string “keyword” didefinisikan, maka akan melakukan pencarian ke tabelusers
. Contoh skripnya adalah sebagai berikut:
// contoh url: domain.com?user/search?keyword=john public function search(\Illuminate\Http\Request $request): \Illuminate\View\View { $users = \App\Users::orderBy('name') ->when($request->keyword, function ($query) use ($request) { return $query->where('name', 'LIKE', '%' . $request->keyword . '%'); }) ->paginate(20); return view('user.search', compact('users')); }
Sampai di ini, kasus sudah terpecahkan? Ya tentu saja. Jika kalian mencoba skrip di atas, fitur pencarian sudah berjalan dengan baik.
Permasalahn terjadi ketika kalian mengklik halaman berikutnya, di mana query string “keyword” tidak terbawa oleh pagination. Sehingga, pencarian di halaman berikutnya menjadi keliru.
// ekspektasi domain.com/user/search?page=2&keyword=john // realita domain.com/user/search?page=2
Untuk menangani kasus ini, kalian diharuskan menggunakan method tambahan dengan nama appends()
untuk membawa query string tambahan pada URL.
$users->appends($request->all());
Atau, kalian juga bisa mengizinkan hanya query string tertentu yang dapat ditambahkan ke dalam pagination.
// contoh url: domain.com/user/search?keyword=1&order=[asc,name]&undefined=string $users->appends($request->only('keyword'));
Selengkapnya mengenai request, dapat kalian baca langsung pada dokumentasinya.
Custom Template
Seperti disebutkan di atas, pagination menggunakan Bootstrap sebagai basis tampilannya. Berkas viewnya sendiri tersimpan pada path:
/vendor/illuminate/pagination/resources/views/default.blade.php
Tentunya, kita tidak direkomendasikan untuk mengubah langsung pada berkas di atas. Hal pertama yang dilakukan adalah menyalin berkas tersebut ke dalam direktori resources/views menggunakan Artisan console.
php artisan vendor:publish --tag=laravel-pagination
Dari perintah di atas, kalian akan mendapati empat buah berkas view dalam direktori resources/views/vendor/pagination
. Nah, keempat berkas inilah yang perlu kalian modifikasi untuk menyesuikan dengan theme yang digunakan.
Bagaimana jika saya menggunakan view lain (selain default.blade.php) dari keempat berkas view di atas? Atau, bisakah saya menggunakan view yang benar-benar saya buat sendiri?
Jabawannya, bisa. Kalian hanya perlu mendefinisikannya pada method links()
.
$users->links('custom.pagination');
Tak hanya sampai di situ, kalian juga bisa melempar variabel lain ke dalam template pagination yang kalian buat sendiri.
$users->links('custom.pagination', compact('foo')); // atau $user->links('custom.pagination', ['foo' => $foo]);
Method dalam Pagination
Selain method links()
, withPath()
, dan appends()
yang saya contohkan di atas, ada beberapa method dari instance pagination yang bisa kalian gunakan untuk pelengkap dalam aplikasi. Daftar method yang tersedia dapat dilihat pada media di bawah:
// dengan asumsi $users merupakan instance dari class pagination // menghitung jumlah data $users->count(); // halaman saat ini $results->currentPage(); // tautan halaman pertama $results->firstItem(); // memiliki halaman berikutnya? $results->hasMorePages(); // tautan data terakhir $results->lastItem() // tautan halaman terakhir $results->lastPage() (tidak tersedia dalam simplePaginate) // tautan halaman berikutnya $results->nextPageUrl(); // jumlah data per halaman $results->perPage(); // tautan halaman sebelumnya $results->previousPageUrl(); // total data $results->total() (tidak tersedia dalam simplePaginate) // tautan halaman $results->url($page)
pak, untuk penggunaan pagination dengan query top (SQL server 2008) bagaimana cara penulisan sintaksnya?