Laravel's powerful Collection class provides many helpful methods for working with arrays of data. However, the built-in paginate
method only works on Eloquent query builder and database results.
If you want to paginate a standard Laravel Collection instance, such as from an array or other custom data source, you're out of luck. Or are you?
By defining a custom macro, we can add pagination capabilities to any Collection instance in Laravel. Here's how it works...
Defining the Pagination Macro
Laravel allows you to define custom macros on existing classes to augment them with new functionality. We can utilize this to create a reusable paginate
macro on the Collection class.
Inside the boot
method of a service provider, like AppServiceProvider
, we'll define the macro:
use Illuminate\Support\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
Collection::macro('paginate', function ($perPage = 15, $pageName = 'page', $page = null, $options = []) {
// Resolve current page from request
$page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);
// Paginate the Collection
return new LengthAwarePaginator(
$this->forPage($page, $perPage),
$this->count(),
$perPage,
$page,
$options
);
});
The macro creates a new LengthAwarePaginator
instance which will handle the pagination render logic and links. We just need to pass the specific page's chunk of data from the collection using forPage
, as well as the total collection count.
Paginating a Collection
With the macro defined, we can now paginate non-DB collections:
$collection = collect(range(1, 100)); // a Collection instance
$paginated = $collection->paginate(10); // 10 items per page
var_dump($paginated->items()); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] on page 1
The macro handles all the complexity of slicing the collection into pages and generating the paginator instance.
Custom Pagination Super Powers!
Defining custom macros provides tremendous flexibility to expand Laravel's base classes. In this case, we've given all collections the ability to be paginated with a simple, expressive syntax.
While less efficient for giant data sets, this approach is great for smaller arrays or collections not coming directly from a database query.
So don't limit yourself to just paginating Eloquent results. With a bit of macro magic, you can bring pagination powers to any Laravel collection!
Top comments (0)