PHPackages                             deepdiver/laravel-cursor-paginator - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. deepdiver/laravel-cursor-paginator

AbandonedLibrary[Database &amp; ORM](/categories/database)

deepdiver/laravel-cursor-paginator
==================================

Cursor pagination for Laravel 8

v2.0.0(5y ago)025.4k[1 issues](https://github.com/DeepDiver1975/laravel-cursor-paginator/issues)MITPHPCI failing

Since Jun 8Pushed 4y ago1 watchersCompare

[ Source](https://github.com/DeepDiver1975/laravel-cursor-paginator)[ Packagist](https://packagist.org/packages/deepdiver/laravel-cursor-paginator)[ RSS](/packages/deepdiver-laravel-cursor-paginator/feed)WikiDiscussions master Synced yesterday

READMEChangelogDependencies (2)Versions (11)Used By (0)

Laravel Cursor Paginator
========================

[](#laravel-cursor-paginator)

[![Build Status](https://camo.githubusercontent.com/1172147379c91945aacd70e31d1df308e4b6988a781bf328f8271ce6ab781072/68747470733a2f2f7472617669732d63692e6f72672f616d726e6e39302f6c61726176656c2d637572736f722d706167696e61746f722e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/amrnn90/laravel-cursor-paginator)

Easily have cursor based pagination in your Eloquent models and query builders, read [this article](https://use-the-index-luke.com/sql/partial-results/fetch-next-page) to understand the benefits of cursor pagination and the problems it attempts to solve.

There's another [cursor-pagination](https://github.com/juampi92/cursor-pagination) package but unfortunately it doesn't support retrieving previous pages or multi-column ordering, that's why I decided to create this one.

### Features

[](#features)

- Automatically paginates based on columns ordering.
- Supports multi-column ordering which makes it easy to have a deterministic row sequence.
- Detects if the model has date casts.
- Mutiple cursor directions:
    - **before**: returns the items before the cursor.
    - **before\_i**: returns the items before the cursor (including the item at the cursor).
    - **after**: returns the items after the cursor.
    - **after\_i**: returns the items after the cursor (including the item at the cursor).

Installation
------------

[](#installation)

First install the package via composer:

```
composer require amrnn/laravel-cursor-paginator
```

You can optionally publish the config file:

```
php artisan vendor:publish --provider="Amrnn\CursorPaginator\PaginatorServiceProvider"
```

### Register service provider

[](#register-service-provider)

The package automatically registers itself, but if you need to you can add the service provider manually.

```
// config/app.php

'providers' => [
    // ...
    Amrnn\CursorPaginator\PaginatorServiceProvider::class,
];
```

Usage
-----

[](#usage)

This package provides a `cursorPaginate()` method that you can invoke on your Eloquent models or query builders:

```
Route::get('/posts', function() {
    return Post::select('id')->orderBy('id', 'desc')->cursorPaginate(5);
})
```

which will return something like this:

```
{
    /**
    * the result items
    */
    "data": [{"id": 10},{"id": 9},{"id": 8},{"id": 7},{"id": 6}],

    /**
    * number of items per page
    */
    "per_page": 5,

    /**
    * total items in result set for your query
    */
    "total": 10,

    /**
    * the following boundary item if you continue to paginate in this direction
    */
    "next_item": { "id": 5 },

    /**
    * navigation urls, you can change the cursor names in the url query string by
    * editing the (directions) array in config file.
    */
    "first_page_url": "http://localhost:8000/posts?after_i=10",
    "last_page_url": "http://localhost:8000/posts?before_i=1",
    "next_page_url": "http://localhost:8000/posts?after=6",
    "prev_page_url": "http://localhost:8000/posts?before=10",

    /*
    * these provide the cursor data structures.
    * they are given in case you want to construct the url manually,
    * but usually you will  just use the urls shown above.
    */
    "current_page": {...},
    "first_page": {...},
    "last_page": {...},
    "next_page": {...},
    "previous_page": {...},

    /*
    * determine if there are more next/previous items
    */
    "has_next": true,
    "has_previous": false,

}
```

### Options

[](#options)

You can pass an optional first argument to `paginateCursor()` to specify the number of items per page (if left empty a default value from config file is used):

```
// will return 10 items per page
Post::orderBy('id')->cursorPaginate(10);
```

The package should automatically determine date casts by inspecting your model. However, if you're invoking the pagination on a plain query builder then you may need to pass a second argument which tells it about the date casts:

```
// no need to specify date casts here
Post::orderBy('created_at')->cursorPaginate(10);

// must tell a plain query builder about the dates
DB::table('posts')
    ->orderBy('created_at')
    ->cursorPaginate(10, ['dates' => ['created_at']]);
```

### Multiple Columns

[](#multiple-columns)

You can order by multiple columns and pagination should work as expected:

```
Post::orderBy('created_at')->orderBy('id')->cursorPaginate();

Post::orderBy('created_at', 'desc')->orderBy('id', 'desc'')->cursorPaginate();
```

> It's not recommended to mix directions (asc, desc) when ordering by multiple columns. Doing that would make using table indexes hard for your database.

### Caveats

[](#caveats)

All the columns that you're ordering by must also appear in your select statement, for example the following won't work:

```
Post::select('id')->orderBy('created_at')->cursorPaginate();
```

You have to do any of the following instead:

```
Post::select('id', 'created_at')->orderBy('created_at')->cursorPaginate();

// or

Post::orderBy('created_at')->cursorPaginate()
```

Config
------

[](#config)

```
return [
    /**
     *
     * Cursor direction names
     *
     * these appear in the url query string, change their mappings if you need to.
     * for example if you change:
     *
     * 'before' => 'b'
     *
     * then your urls might look like:
     * http://localhost:8000/b=10 instead of http://localhost:8000/before=10
     */
    'directions' => [
        'before' => 'before',
        'before_i' => 'before_i',
        'after' => 'after',
        'after_i' => 'after_i',
    ],

    /**
     * Whether to encode url query.
     *
     * If set to true then your urls might look like:
     * http://localhost:8000/cursor=eyJhZnRlciI6M30 instead of http://localhost:8000/after=3
     */
    'encode_cursor' => false,

    /**
     * Cursor url query name to use when `encode_cursor` set to is `true`.
     *
     * for example if you change:
     * 'encoded_cursor_name' => 'page-id'
     *
     * then your urls might look like:
     * http://localhost:8000/page-id=eyJhZnRlciI6M30 instead of http://localhost:8000/cursor=eyJhZnRlciI6M30
     */
    'encoded_cursor_name' => 'cursor',

    /**
     * Default number of items per page.
     *
     * This can be overridden by passing a first argument to the `cursorPaginate()` method.
     */
    'per_page' => 10,
];
```

License
-------

[](#license)

This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.

###  Health Score

32

—

LowBetter than 72% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity20

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 64.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~46 days

Recently: every ~70 days

Total

10

Last Release

2115d ago

Major Versions

v1.1.1 → v2.0.02020-07-27

### Community

Maintainers

![](https://www.gravatar.com/avatar/d67e9033951a9f2f95737cee73f0f22346a84e4caca86283e811059265e2121b?d=identicon)[DeepDiver1975](/maintainers/DeepDiver1975)

---

Top Contributors

[![amrnn90](https://avatars.githubusercontent.com/u/38134195?v=4)](https://github.com/amrnn90 "amrnn90 (40 commits)")[![DeepDiver1975](https://avatars.githubusercontent.com/u/1005065?v=4)](https://github.com/DeepDiver1975 "DeepDiver1975 (16 commits)")[![jaiselrahman](https://avatars.githubusercontent.com/u/13470226?v=4)](https://github.com/jaiselrahman "jaiselrahman (4 commits)")[![trevorgehman](https://avatars.githubusercontent.com/u/3209864?v=4)](https://github.com/trevorgehman "trevorgehman (2 commits)")

---

Tags

laravelpaginationeloquentcursor

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/deepdiver-laravel-cursor-paginator/health.svg)

```
[![Health](https://phpackages.com/badges/deepdiver-laravel-cursor-paginator/health.svg)](https://phpackages.com/packages/deepdiver-laravel-cursor-paginator)
```

###  Alternatives

[rtconner/laravel-likeable

Trait for Laravel Eloquent models to allow easy implementation of a 'like' or 'favorite' or 'remember' feature.

394388.0k5](/packages/rtconner-laravel-likeable)[highsolutions/eloquent-sequence

A Laravel package for easy creation and management sequence support for Eloquent models with elastic configuration.

121130.3k](/packages/highsolutions-eloquent-sequence)[cybercog/laravel-nova-ban

A Laravel Nova banning functionality for your application.

40199.8k](/packages/cybercog-laravel-nova-ban)[omalizadeh/laravel-query-filter

A laravel package for resource filtering via request query string

163.0k](/packages/omalizadeh-laravel-query-filter)[phaza/single-table-inheritance

Single Table Inheritance Trait

1515.8k](/packages/phaza-single-table-inheritance)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
