Jumat, 14 July 2023

Merubah Collection Menjadi Pagination di Laravel

Dalam artikel ini saya akan menunjukkan Anda bagaimana cara membuat collection menjadi sebuah pagination dalam laravel.

Laravel
Tips and Tricks

Dalam artikel ini saya akan menunjukkan Anda bagaimana cara membuat collection menjadi sebuah pagination dalam laravel.

Wait a minute?

Mungkin Anda pernah berfikir, kenapa kita butuh pagination di dalam collection. Sebenarnya itu tergantung dari kebutuhan kita. Jika kita ingin menampilkan data secara terbatas, maka kita bisa menggunakan pagination. Jika kita ingin menampilkan semua data, maka kita tidak perlu menggunakan pagination.

Kasus yang sering di hadapi adalah ketika kita ingin melakukan looping terhadap static page yang kita punya. Misalnya itu entah blog post yang dibuat di dalam 1 folder dengan prefix extension .md biasanya. Nah ini kan bukan data yang ada di database, sehingga kita tidak bisa menggunakan hal seperti:

$posts = Post::paginate(10);

Namun hal itu tetap harus kita lakukan, oleh karena itu kita harus membuat sebuah pagination untuk collection yang kita punya.

LengthAwarePaginator

Untuk membuat pagination, kita bisa menggunakan class LengthAwarePaginator yang ada di dalam package illuminate/pagination. Tentu untuk membuat nya bisa di akses secara global, kita tentu bisa membuat helper function yang kemudian kita dump lewat composer.

Namun, jika kita bisa mendaftarkannya sebagai macro di dalam class Collection, kenapa tidak.

Sehingga dengan teknik ini, kita dapat dengan mudah memanggilnya dengan seperti ini:

$posts = collect($posts)->paginate(10);

Membuat Macro

Untuk membuat macro ini, silakan buka file app/Providers/AppServiceProvider.php dan tambahkan kode berikut tepat pada metode boot seperti:

app/Providers/AppServiceProvider.php
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Request;
use Illuminate\Pagination\LengthAwarePaginator;

public function boot(): void
{
    Collection::macro('paginate', function ($perPage = 15, $page = null, $options = []) {
        $page = $page ?: (LengthAwarePaginator::resolveCurrentPage() ?: 1);
        $paginator = new LengthAwarePaginator(
            items: $this->forPage($page, $perPage),
            total: $this->count(),
            perPage: $perPage,
            currentPage: $page,
            options: $options
        );

        return $paginator->withPath(Request::url());
    });
}

Penjelasan

Dalam kode ini, kami telah membuat sebuah makro bernama paginate yang dapat digunakan pada setiap Collection. Fungsi paginate menerima 3 parameter:

  1. $perPage - jumlah item yang ditampilkan per halaman.
  2. $page - nomor halaman saat ini.
  3. $options - pilihan tambahan yang akan diteruskan ke LengthAwarePaginator.

Metode forPage mengambil sebagian dari koleksi untuk halaman saat ini, dan LengthAwarePaginator membuat sebuah instance paginator yang mengetahui jumlah total item.

Penggunaan

Dengan begitu, kita bisa memanggil method paginate di dalam collection yang kita punya. Jika kita ingin menampilkan semua data, kita bisa menggunakan method all seperti ini:

$posts = collect($posts)->all();

Dengan begitu, kita akan mendapatkan data yang dibungkus dengan pagination.

Real World Example

Disini saya akan membuat semacam simpel routing untuk nemapilkan 1 - 100 data yang ada di dalam collection. Untuk itu, saya akan membuat sebuah route seperti ini:

routes/web.php
Route::get('/', function () {
    $collection = collect(range(1, 100))->paginate(12);
    return view('welcome', compact('collection'));
});

Kemudian tepat pada welcome.blade.php, kita bisa menampilkan nya dengan mudah seperti:

resources/views/welcome.blade.php
<div class="container py-16 mx-auto">
    <div class="grid grid-cols-4 gap-4">
        @foreach($collection as $item)
            <div class="p-10 bg-slate-500">
                {{ $item }}
            </div>
        @endforeach
    </div>
    
    {{ $collection->links() }}
</div>

Perlu diingat bahwa jenis paginasi seperti ini tidak memanfaatkan fitur paginasi level query, karena metode ini akan memuat semua data ke dalam koleksi sebelum melakukan paginasi.

Kesimpulan

Merubah collection menjadi sebuah pagination tentu tidak sulit bagi laravel sendiri, namun kenapa mereka tidak membuatnya ada by default. Kan itu jadi pertanyaan kita.

Jadi, harap berhati-hati saat menggunakan metode ini pada set data yang besar karena bisa menyebabkan masalah kehabisan memori. Dalam kasus semacam itu, selalu lebih baik untuk melakukan paginasi pada level database.

Semoga artikel ini bermanfaat, terima kasih dan sampai jumpa di artikel selanjutnya.