Pagination di Laravel itu Mudah!


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.

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 tabelusersdengan 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.

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 datausersper halaman.

Menampilkan dalam Bentuk JSON

Menampilkan data + pagination cukup mudah. Alih-alih menggunakan method view() untuk memuat tampilkan, kalian bisa menampilkannya langsung dengan classJsonResponsemenggunakan 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)
Tak Berkategori

Yugo Purwanto

Pemrogram PHP dan JavaScript yang sedang sibuk mengembangkan aplikasi Glosarium Bahasa Indonesia.

Tinggalkan Balasan