{"id":13684410,"url":"https://github.com/lampager/lampager-cakephp","last_synced_at":"2025-12-25T02:56:00.086Z","repository":{"id":26154478,"uuid":"107501237","full_name":"lampager/lampager-cakephp","owner":"lampager","description":"Rapid pagination for CakePHP","archived":false,"fork":false,"pushed_at":"2024-04-21T12:36:59.000Z","size":98,"stargazers_count":5,"open_issues_count":0,"forks_count":3,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-10-26T13:42:53.896Z","etag":null,"topics":["cakephp","cakephp-plugin","fast","pagination","paginator","php"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lampager.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-10-19T05:17:14.000Z","updated_at":"2024-04-21T12:21:06.000Z","dependencies_parsed_at":"2024-04-21T12:35:46.359Z","dependency_job_id":"8f982d76-b36f-40ee-8543-d60b5b3a8b62","html_url":"https://github.com/lampager/lampager-cakephp","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lampager%2Flampager-cakephp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lampager%2Flampager-cakephp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lampager%2Flampager-cakephp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lampager%2Flampager-cakephp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lampager","download_url":"https://codeload.github.com/lampager/lampager-cakephp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224224786,"owners_count":17276428,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cakephp","cakephp-plugin","fast","pagination","paginator","php"],"created_at":"2024-08-02T14:00:33.215Z","updated_at":"2025-12-25T02:56:00.063Z","avatar_url":"https://github.com/lampager.png","language":"PHP","readme":"\u003cp align=\"center\"\u003e\n\u003cimg width=\"320\" alt=\"lampager-cakephp\" src=\"https://user-images.githubusercontent.com/1351893/31820647-42c45c7a-b5dd-11e7-9ac8-f1000e961662.png\"\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://github.com/lampager/lampager-cakephp/actions/workflows/ci.yml?query=branch:master\"\u003e\u003cimg src=\"https://github.com/lampager/lampager-cakephp/actions/workflows/ci.yml/badge.svg?branch=master\" alt=\"CI Workflow\"\u003e\u003c/a\u003e\n\u003ca href=\"https://coveralls.io/github/lampager/lampager-cakephp?branch=master\"\u003e\u003cimg src=\"https://coveralls.io/repos/github/lampager/lampager-cakephp/badge.svg?branch=master\" alt=\"Coverage Status\"\u003e\u003c/a\u003e\n\u003ca href=\"https://scrutinizer-ci.com/g/lampager/lampager-cakephp/?branch=master\"\u003e\u003cimg src=\"https://scrutinizer-ci.com/g/lampager/lampager-cakephp/badges/quality-score.png?b=master\" alt=\"Scrutinizer Code Quality\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# Lampager for CakePHP\n\nRapid pagination without using OFFSET\n\n## Requirements\n\n- PHP: ^8.1\n- CakePHP: ^5.1\n- [lampager/lampager][]: ^0.4\n\n### Note\n\n- For CakePHP 2.x, use [lampager/lampager-cakephp2][].\n- For CakePHP 3.x, use [lampager/lampager-cakephp v1.x][].\n- For CakePHP 4.x, use [lampager/lampager-cakephp v2.x][].\n- For CakePHP 5.x, use lampager/lampager-cakephp v3.x (this version).\n\n## Installing\n\n```bash\ncomposer require lampager/lampager-cakephp:^3.0\n```\n\nFor SQLite users, see [SQLite](#sqlite) to configure.\n\n## Basic Usage\n\nSimply install as a Composer package and use in one or more of the following\nmethods:\n\n- Use in Controller (via `\\Lampager\\Cake\\Datasource\\Paginator`)\n- Use in Table (via `\\Lampager\\Cake\\Model\\Behavior\\LampagerBehavior`)\n\n### Use in Controller\n\nAt first, configure `$paginate` to use `\\Lampager\\Cake\\Datasource\\Paginator` in\nyour Controller class.\n\n```php\nnamespace App\\Controller;\n\nuse Cake\\Controller\\Controller;\nuse Lampager\\Cake\\Datasource\\Paginator;\n\nclass AppController extends Controller\n{\n    public $paginate = [\n        'className' =\u003e Paginator::class,\n    ];\n}\n```\n\nUse in a way described in the Cookbook: [Pagination][]. Note the options that\nare specific to Lampager such as `forward`, `seekable`, or `cursor`.\n\n```php\n$query = $this-\u003ePosts\n    -\u003ewhere(['Posts.type' =\u003e 'public'])\n    -\u003eorderByDesc('created')\n    -\u003eorderByDesc('id')\n    -\u003elimit(10);\n\n$posts = $this-\u003epaginate($query, [\n    'forward' =\u003e true,\n    'seekable' =\u003e true,\n    'cursor' =\u003e [\n        'id' =\u003e 4,\n        'created' =\u003e '2020-01-01 10:00:00',\n    ],\n]);\n\n$this-\u003eset('posts', $posts);\n```\n\n### Use in Table\n\nInitialize `LampagerBehavior` in your Table class (`AppTable` is preferable)\nand simply use `lampager()` there.\n\n```php\nnamespace App\\Model\\Table;\n\nuse Cake\\ORM\\Table;\nuse Lampager\\Cake\\Model\\Behavior\\LampagerBehavior;\n\nclass AppTable extends Table\n{\n    public function initialize(array $config): void\n    {\n        parent::initialize($config);\n\n        $this-\u003eaddBehavior(LampagerBehavior::class);\n    }\n}\n```\n\nThe query builder (`\\Lampager\\Cake\\ORM\\Query`) extends the plain old\n`\\Cake\\ORM\\Query` and is mixed in with `\\Lampager\\Paginator`. Note that some of\nthe methods in `\\Lampager\\Paginator`, viz., `orderBy()`, `orderByDesc()`, and\n`clearOrderBy()` are not exposed because their method signatures are not\ncompatible with the CakePHP query builder.\n\n```php\n$cursor = [\n    'id' =\u003e 4,\n    'created' =\u003e '2020-01-01 10:00:00',\n    'modified' =\u003e '2020-01-01 12:00:00',\n];\n\n/** @var \\Lampager\\Cake\\PaginationResult $latest */\n$latest = $this-\u003elampager()\n    -\u003eforward()\n    -\u003eseekable()\n    -\u003ecursor($cursor)\n    -\u003elimit(10)\n    -\u003eorderByDesc('Posts.modified')\n    -\u003eorderByDesc('Posts.created')\n    -\u003eorderByDesc('Posts.id')\n    -\u003epaginate();\n\nforeach ($latest as $post) {\n    /** @var \\Cake\\ORM\\Entity $post */\n    debug($post-\u003eid);\n    debug($post-\u003ecreated);\n    debug($post-\u003emodified);\n}\n```\n\nThe methods from the CakePHP query builder, e.g., `where()`, are available.\n`\\Cake\\Database\\Expression\\QueryExpression` is accepted as well.\n\n```php\n/** @var \\Lampager\\Cake\\PaginationResult $drafts */\n$drafts = $this-\u003elampager()\n    -\u003ewhere(['type' =\u003e 'draft'])\n    -\u003eforward()\n    -\u003eseekable()\n    -\u003ecursor($cursor)\n    -\u003elimit(10)\n    -\u003eorderByDesc($this-\u003eselectQuery()-\u003enewExpr('modified'))\n    -\u003eorderByDesc($this-\u003eselectQuery()-\u003enewExpr('created'))\n    -\u003eorderByDesc($this-\u003eselectQuery()-\u003enewExpr('id'))\n    -\u003epaginate();\n\n/** @var \\Cake\\ORM\\Entity $sample */\n$sample = $drafts-\u003esample();\n\n/** @var int $count */\n$count = $drafts-\u003ecount();\n```\n\n## Classes\n\nSee also: [lampager/lampager][].\n\n| Name                                                | Type  | Parent Class\u003cbr\u003eImplemented Interface                                          | Description                                                                         |\n|:----------------------------------------------------|:------|:-------------------------------------------------------------------------------|:------------------------------------------------------------------------------------|\n| Lampager\\\\Cake\\\\ORM\\\\`Query`                        | Class | Cake\\\\ORM\\\\`Query`                                                             | Fluent factory implementation for CakePHP                                           |\n| Lampager\\\\Cake\\\\Model\\\\Behavior\\\\`LampagerBehavior` | Class | Cake\\\\ORM\\\\`Behavior`                                                          | CakePHP behavior which returns Lampager\\\\Cake\\\\ORM\\\\`Query`                         |\n| Lampager\\\\Cake\\\\Datasource\\\\`Paginator`             | Class | Cake\\\\Datasource\\\\`Paginator`                                                  | CakePHP paginatior which delegates to Lampager\\\\Cake\\\\ORM\\\\`Query`                  |\n| Lampager\\\\Cake\\\\`Paginator`                         | Class | Lampager\\\\`Paginator`                                                          | Paginator implementation for CakePHP                                                |\n| Lampager\\\\Cake\\\\`ArrayProcessor`                    | Class | Lampager\\\\`ArrayProcessor`                                                     | Processor implementation for CakePHP                                                |\n| Lampager\\\\Cake\\\\`PaginationResult`                  | Class | Lampager\\\\`PaginationResult`\u003cbr\u003eCake\\\\Datasource\\\\Paging\\\\`PaginatedInterface` | PaginationResult implementation for CakePHP                                         |\n| Lampager\\\\Cake\\\\Database\\\\`SqliteCompiler`          | Class | Cake\\\\Database\\\\`QueryCompiler`                                                | Query compiler implementation for SQLite                                            |\n| Lampager\\\\Cake\\\\Database\\\\Driver\\\\`Sqlite`          | Class | Cake\\\\Database\\\\Driver\\\\`Sqlite`                                               | Driver implementation which delegates to Lampager\\\\Cake\\\\Database\\\\`SqliteCompiler` |\n\n## API\n\nSee also: [lampager/lampager][].\n\n### LampagerBehavior::lampager()\n\nBuild a Lampager query from Table in exactly the same way as CakePHP.\n\n```php\nLampagerBehavior::lampager(): \\Lampager\\Cake\\ORM\\Query\n```\n\n### Paginator::\\_\\_construct()\u003cbr\u003ePaginator::create()\n\nCreate a new paginator instance. These methods are not intended to be directly\nused in your code.\n\n```php\nstatic Paginator::create(\\Cake\\ORM\\Query\\SelectQuery $builder): static\nPaginator::__construct(\\Cake\\ORM\\Query\\SelectQuery $builder)\n```\n\n### Paginator::transform()\n\nTransform a Lampager query into a CakePHP query.\n\n```php\nPaginator::transform(\\Lampager\\Query $query): \\Cake\\ORM\\Query\\SelectQuery\n```\n\n### Paginator::build()\n\nPerform configure + transform.\n\n```php\nPaginator::build(\\Lampager\\Contracts\\Cursor|array $cursor = []): \\Cake\\ORM\\Query\\SelectQuery\n```\n\n### Paginator::paginate()\n\nPerform configure + transform + process.\n\n```php\nPaginator::paginate(\\Lampager\\Contracts\\Cursor|array $cursor = []): \\Lampager\\Cake\\PaginationResult\n```\n\n#### Arguments\n\n- **`(mixed)`** __*$cursor*__\u003cbr\u003e An associative array that contains `$column =\u003e $value` or an object that implements `\\Lampager\\Contracts\\Cursor`. It must be **all-or-nothing**.\n  - For the initial page, omit this parameter or pass an empty array.\n  - For the subsequent pages, pass all the parameters. The partial one is not allowed.\n\n#### Return Value\n\ne.g.,\n\n(Default format when using `\\Cake\\ORM\\Query`)\n\n```php\nobject(Lampager\\Cake\\PaginationResult)#1 (6) {\n  [\"(help)\"]=\u003e\n  string(44) \"This is a Lampager Pagination Result object.\"\n  [\"records\"]=\u003e\n  array(3) {\n    [0]=\u003e\n    object(Cake\\ORM\\Entity)#2 (11) { ... }\n    [1]=\u003e\n    object(Cake\\ORM\\Entity)#3 (11) { ... }\n    [2]=\u003e\n    object(Cake\\ORM\\Entity)#4 (11) { ... }\n  [\"hasPrevious\"]=\u003e\n  bool(false)\n  [\"previousCursor\"]=\u003e\n  NULL\n  [\"hasNext\"]=\u003e\n  bool(true)\n  [\"nextCursor\"]=\u003e\n  array(2) {\n    [\"created\"]=\u003e\n    object(Cake\\I18n\\Time)#5 (3) {\n      [\"date\"]=\u003e\n      string(26) \"2017-01-01 10:00:00.000000\"\n      [\"timezone_type\"]=\u003e\n      int(3)\n      [\"timezone\"]=\u003e\n      string(3) \"UTC\"\n    }\n    [\"id\"]=\u003e\n    int(1)\n  }\n}\n```\n\n### PaginationResult::\\_\\_call()\n\n`\\Lampager\\Cake\\PaginationResult` implements\n`\\Cake\\Datasource\\Paging\\PaginatedInterface`.\n\n## Examples\n\nThis section describes the practical usage of lampager-cakephp.\n\n### Use in Controller\n\nThe example below shows how to accept a cursor parameter from a request and pass\nit through `PaginatorComponent::paginate()`. Be sure that your `AppController`\nhas properly initialized `Paginator` as above.\n\n```php\nnamespace App\\Controller;\n\nclass PostsController extends AppController\n{\n    public $Posts = null;\n\n    /**\n     * This method shows how to pass options by a query and array.\n     */\n    public function query(): void\n    {\n        // Get cursor parameters\n        $previous = json_decode($this-\u003erequest-\u003egetQuery('previous_cursor'), true);\n        $next = json_decode($this-\u003erequest-\u003egetQuery('next_cursor'), true);\n        $cursor = $previous ?: $next ?: [];\n\n        // Query expression can be passed to PaginatorComponent::paginate() as normal\n        $query = $this-\u003ePosts\n            -\u003ewhere(['Posts.type' =\u003e 'public'])\n            -\u003eorderByDesc('created')\n            -\u003eorderByDesc('id')\n            -\u003elimit(15);\n\n        /** @var \\Lampager\\Cake\\PaginationResult\u003c\\Cake\\ORM\\Entity\u003e $posts */\n        $posts = $this-\u003epaginate($query, [\n            // If the previous_cursor is not set, paginate forward; otherwise backward\n            'forward' =\u003e !$previous,\n            'cursor' =\u003e $cursor,\n            'seekable' =\u003e true,\n        ]);\n\n        $this-\u003eset('posts', $posts);\n    }\n\n    /**\n     * This method shows how to pass options from an array.\n     */\n    public function options(): void\n    {\n        // Get cursor parameters\n        $previous = json_decode($this-\u003erequest-\u003egetQuery('previous_cursor'), true);\n        $next = json_decode($this-\u003erequest-\u003egetQuery('next_cursor'), true);\n        $cursor = $previous ?: $next ?: [];\n\n        /** @var \\Lampager\\Cake\\PaginationResult\u003c\\Cake\\ORM\\Entity\u003e $posts */\n        $posts = $this-\u003epaginate('Posts', [\n            // Lampager options\n            // If the previous_cursor is not set, paginate forward; otherwise backward\n            'forward' =\u003e !$previous,\n            'cursor' =\u003e $cursor,\n            'seekable' =\u003e true,\n\n            // PaginatorComponent config\n            'conditions' =\u003e [\n                'type' =\u003e 'public',\n            ],\n            'order' =\u003e [\n                'created' =\u003e 'DESC',\n                'id' =\u003e 'DESC',\n            ],\n            'limit' =\u003e 15,\n        ]);\n\n        $this-\u003eset('posts', $posts);\n    }\n}\n```\n\nAnd the pagination links can be output as follows:\n\n```php\n// If there is a next page, print pagination link\nif ($posts-\u003ehasPrevious) {\n    echo $this-\u003eHtml-\u003elink('\u003c\u003c Previous', [\n        'controller' =\u003e 'posts',\n        'action' =\u003e 'index',\n        '?' =\u003e [\n            'previous_cursor' =\u003e json_encode($posts-\u003epreviousCursor),\n        ],\n    ]);\n}\n\n// If there is a next page, print pagination link\nif ($posts-\u003ehasNext) {\n    echo $this-\u003eHtml-\u003elink('Next \u003e\u003e', [\n        'controller' =\u003e 'posts',\n        'action' =\u003e 'index',\n        '?' =\u003e [\n            'next_cursor' =\u003e json_encode($posts-\u003enextCursor),\n        ],\n    ]);\n}\n```\n\n## Supported database engines\n\n### MySQL, MariaDB, and PostgreSQL\n\nSupported!\n\n### Microsoft SQL Server\n\nNot supported.\n\n### SQLite\n\nSupported but requires an additional configuration.\n\nIn SQLite `UNION ALL` statements cannot combine `SELECT` statements that have\n`ORDER BY` clause. In order to get this to work, those `SELECT` statements have\nto be wrapped by a subquery like `SELECT * FROM (...)`. CakePHP not natively\nhandling this situation, Lampager for CakePHP introduces\n`\\Lampager\\Cake\\Database\\Driver\\Sqlite` that needs to be installed on your\napplication. Configure like the following in your `config/app.php`:\n\n```php\nreturn [\n    'Datasources' =\u003e [\n        'default' =\u003e [\n            'className' =\u003e Connection::class,\n            'driver' =\u003e \\Lampager\\Cake\\Database\\Driver\\Sqlite::class,\n            'username' =\u003e '********',\n            'password' =\u003e '********',\n            'database' =\u003e '********',\n        ],\n    ],\n];\n```\n\n[lampager/lampager]:              https://github.com/lampager/lampager\n[lampager/lampager-cakephp v1.x]: https://github.com/lampager/lampager-cakephp/tree/v1.x\n[lampager/lampager-cakephp v2.x]: https://github.com/lampager/lampager-cakephp/tree/v2.x\n[lampager/lampager-cakephp2]:     https://github.com/lampager/lampager-cakephp2\n[Pagination]:                     https://book.cakephp.org/5/en/controllers/pagination.html\n","funding_links":[],"categories":["ORM / Database / Datamapping"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flampager%2Flampager-cakephp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flampager%2Flampager-cakephp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flampager%2Flampager-cakephp/lists"}