aloware/laravel-cursor-pagination

Cursor pagination for Laravel

v1.0.9 2022-12-06 19:55 UTC

README

This package provides cursor based pagination for Laravel's Query Builder and Eloquent ORM. It calculates the SQL query limits automatically by checking the requests GET parameters, and automatically builds the next and previous urls for you.

Compatibility

This package is tested on Laravel 5.6, and we expect it to work on newer versions, but it was never tested.

Installation

You can install this package via composer using:

composer require aloware/laravel-cursor-pagination

The package will automatically register itself.

How does it work

The main idea behind a cursor pagination is that it needs a context to know what results to show next. So instead of saying page=2, you say:

cursor=eyJpZCI6MTAsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0=

and the cursor value is encoded(base64). If you decode it, you'll we something like:

{"id":10,"_pointsToNextItems":true}

The result is the same as the old fashioned page pagination, but now you have more control on the output, cause it should always return the same.

This kind of pagination is useful when you sort using the latest first, so you can keep an infinite scroll using cursor whenever you get to the bottom, or do a cursor whenever you need to refresh the list at the top, and if you send the first cursor, the results will only fetch the new ones.

Basic Usage

Paginating Query Builder Results

There are several ways to paginate items. The simplest is by using the cursorPaginate method on the query builder or an Eloquent query. The cursorPaginate method automatically takes care of setting the proper limit and fetching the next or previous elements based on the cursor being viewed by the user. By default, the cursor is detected by the value of the page query string argument on the HTTP request. This value is automatically detected by the package taking your custom config into account, and is also automatically inserted into links and meta generated by the paginator.

public function index()
{
    $users = DB::table('users')->cursorPaginate();
    return $users;
}

Paginating Eloquent Results

You may also paginate Eloquent queries. In this example, we will paginate the User model with 15 items per page. As you can see, the syntax is identical to paginating query builder results:

$users = User::cursorPaginate(15);

Of course, you may call paginate after setting other constraints on the query, such as where clauses:

$users = User::where('votes', '>', 100)->cursorPaginate(15);

Or sorting your results:

$users = User::orderBy('id', 'desc')->cursorPaginate(15);

Don't worry, the package will detect if the model's primary key is being used for sorting, and it will adapt itself so the next and previous work as expected.

Identifier

The paginator identifier is basically the cursor attribute. The model's attribute that will be used for paginating. It's really important that this identifier is unique on the results. Duplicated identifiers could cause that some records are not showed, so be careful.

Auto-detecting Identifier

If no identifier is defined, the cursor will try to figure it out by itself. First, it will check if there's any orderBy clause. If there is, it will take the first column that is sorted and will use that. If there is not any orderBy clause, it will check if it's an Eloquent model, and will use it's primaryKey (by default it's 'id'). And if it's not an Eloquent Model, it'll use id.

Example
// Will use Booking's primaryKey
Bookings::cursorPaginate(10);
// Will use hardcoded 'id'
DB::table('bookings')->cursorPaginate(10);
// Will use 'created_by'
Bookings::orderBy('created_by', 'asc')
    ->cursorPaginate(10);

Customizing Identifier

Just define the identifier option

// Will use id, ignoring everything else.
Bookings::cursorPaginate(10, ['*'], 'cursor', 'id');

Credits

License

The MIT License (MIT). Please see License File for more information.