PHPackages                             muxtorov/yii2-cursor-pagination - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. muxtorov/yii2-cursor-pagination

ActiveYii2-extension[Utility &amp; Helpers](/categories/utility)

muxtorov/yii2-cursor-pagination
===============================

Cursor-based pagination helper for Yii2 APIs

v1.0.0(2mo ago)11MITPHPPHP &gt;=7.4

Since Apr 6Pushed 2mo agoCompare

[ Source](https://github.com/Muxtorov98/yii2-cursor-pagination)[ Packagist](https://packagist.org/packages/muxtorov/yii2-cursor-pagination)[ RSS](/packages/muxtorov-yii2-cursor-pagination/feed)WikiDiscussions main Synced 1w ago

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

yii2-cursor-pagination
======================

[](#yii2-cursor-pagination)

Cursor-based pagination helper for Yii2 APIs with PHP `7.4` and `8+` support.

Install
-------

[](#install)

```
composer require muxtorov/yii2-cursor-pagination
```

Config
------

[](#config)

`config/params.php`

```
return [
    'pagination' => [
        'maxLimit' => 1000,
        'defaultPerPage' => 20,
        'cursorParam' => 'cursor',
        'perPageParam' => 'per-page',
        'directionParam' => 'direction',
    ],
];
```

Simple usage
------------

[](#simple-usage)

```
use Muxtorov\Yii2CursorPagination\CursorDataProvider;

$provider = new CursorDataProvider();

$data = $provider->getData(
    OrderResource::find()->where(['userId' => $userId]),
    ['createdAt', 'id']
);
```

Response shape:

```
[
    'items' => [...],
    '_links' => [
        'self' => '...',
        'next' => '...',
        'prev' => '...',
    ],
    '_meta' => [
        'perPage' => 20,
        'direction' => 'next',
        'hasNext' => true,
        'hasPrev' => false,
        'nextCursor' => '...',
        'prevCursor' => '...',
    ],
]
```

Query params
------------

[](#query-params)

```
GET /orders?per-page=20
GET /orders?cursor=eyJpZCI6MTAwfQ&direction=next
GET /orders?cursor=eyJpZCI6MTAwfQ&direction=prev

```

Defaults:

- `cursor`: current page cursor
- `per-page`: page size
- `direction`: `next` or `prev`

Recommended architecture
------------------------

[](#recommended-architecture)

This package should stay generic.

Keep these inside your project:

- `BaseFilter`
- `QueryCollectionExtensionInterface`
- `DefaultFilter`
- factory classes like `api\modules\v1\factories\*`
- project-specific query extensions

Keep this package responsible only for:

- reading request cursor params
- applying cursor condition
- building `_links`
- building `_meta`

That separation is important because `BaseFilter` and your extensions are application-specific orchestration, not package-level generic logic.

Full integration with BaseFilter pattern
----------------------------------------

[](#full-integration-with-basefilter-pattern)

If your project already uses this style:

- `BaseFilter`
- `QueryCollectionExtensionInterface`
- `Factory`
- `Extension`
- `Controller`

then the correct approach is:

1. Keep package generic.
2. Inject or instantiate `CursorDataProvider` inside your local `BaseFilter`.
3. Let factories decide which cursor columns to use.

BaseFilter integration example
------------------------------

[](#basefilter-integration-example)

Example local project class:

```
