{"id":23058337,"url":"https://github.com/germaniakg/pagination","last_synced_at":"2025-04-03T06:17:11.625Z","repository":{"id":62510170,"uuid":"175608954","full_name":"GermaniaKG/Pagination","owner":"GermaniaKG","description":"Pagination Calculator for large collections. Good for JsonAPI and paginated output.","archived":false,"fork":false,"pushed_at":"2022-05-30T14:22:55.000Z","size":39,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-08T20:12:44.345Z","etag":null,"topics":["arrays","jsonapi","paginated-results","pagination","traversable"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GermaniaKG.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-03-14T11:31:47.000Z","updated_at":"2022-03-30T10:04:55.000Z","dependencies_parsed_at":"2022-11-02T12:46:31.263Z","dependency_job_id":null,"html_url":"https://github.com/GermaniaKG/Pagination","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GermaniaKG%2FPagination","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GermaniaKG%2FPagination/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GermaniaKG%2FPagination/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GermaniaKG%2FPagination/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GermaniaKG","download_url":"https://codeload.github.com/GermaniaKG/Pagination/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246944385,"owners_count":20858772,"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":["arrays","jsonapi","paginated-results","pagination","traversable"],"created_at":"2024-12-16T02:15:07.259Z","updated_at":"2025-04-03T06:17:11.603Z","avatar_url":"https://github.com/GermaniaKG.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Germania KG · Pagination\n\n\n\n\n[![Packagist](https://img.shields.io/packagist/v/germania-kg/pagination.svg?style=flat)](https://packagist.org/packages/germania-kg/pagination)\n[![PHP version](https://img.shields.io/packagist/php-v/germania-kg/pagination.svg)](https://packagist.org/packages/germania-kg/pagination)\n[![Build Status](https://img.shields.io/travis/GermaniaKG/Pagination.svg?label=Travis%20CI)](https://travis-ci.org/GermaniaKG/Pagination)\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/GermaniaKG/Pagination/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/GermaniaKG/Pagination/?branch=master)\n[![Code Coverage](https://scrutinizer-ci.com/g/GermaniaKG/Pagination/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/GermaniaKG/Pagination/?branch=master)\n[![Build Status](https://scrutinizer-ci.com/g/GermaniaKG/Pagination/badges/build.png?b=master)](https://scrutinizer-ci.com/g/GermaniaKG/Pagination/build-status/master)\n\n\n\n## Installation with Composer\n\n```bash\n$ composer require germania-kg/pagination\n```\n\n\n\n## Overview\n\n**Pagination:**\nPage numbering made easy! Supports *current, next, previous, first* and *last* page numbers as well as *number of pages* and customizable *page sizes*.\n\n**PaginationFactory:**\nCallable class for creating a *Pagination* instance. Works great with `$_GET['page']`\n\n**PaginationIterator:**\nLimits your *Traversables* according to the *Pagination* status. Useful for paginated **JSON API** resources. \n\n**JsonApiPaginationDecorator:** \nCreate useful `links` and `meta` information for your **JSON API** resource collection.\n\n\n\n## Usage\n\n### The Pagination class\n\nJust pass the number of items to paginate. The *Pagination* class will calculate the page numbers, based on a default page size of 25. See below for customization examples.\n\n```php\n\u003c?hpp\nuse Germania\\Pagination\\Pagination;\n\n$items_count = 100; // count( $things ) or integer;\n$pagination = new Pagination( $items_count );\n\n$pagination-\u003egetPagesCount(); // 4, with 25 items each\n$pagination-\u003egetFirst(); // 0\n$pagination-\u003egetLast(); // 3\n```\n\n\n\n#### Pagination status\n\nRight after instantiation, no page was picked by the user. Hence, the *Pagination* is then considered *inactive*. \n\nPlease note that the current page also may be `int(0)` – the first page. This is why we have to check against `null`. The *isActive* method is a convenient alias for `$p-\u003egetCurrent() === null` . \n\n```php\n$pagination-\u003eisActive();    // FALSE\n\n$pagination-\u003egetCurrent();  // null\n$pagination-\u003egetPrevious(); // null\n$pagination-\u003egetNext();     // null\n```\n\nIt first needs a *setCurrent* call to become *active*:\n\n#### Setting the current page\n\n```php\nuse Germania\\Pagination\\PaginationRangeException;\n\ntry {\n  $pagination-\u003esetCurrent( 1 );\n  \n  $pagination-\u003eisActive();    // TRUE\n  $pagination-\u003egetCurrent();  // 1  \n  $pagination-\u003egetPrevious(); // null\n  $pagination-\u003egetNext();     // 2  \n}\ncatch ( PaginationRangeException $e )\n{\n  echo $e-\u003egetMessage(); // \"Invalid Page number\"\n  echo $e-\u003egetCode();    // 400\n}\n```\n\n\n\n#### Setting the page size\n\nWhilst the default number of items on a page is 25, you may set another size—up to 100 per default:\n\n```php\nuse Germania\\Pagination\\PaginationRangeException;\n\ntry {\n\t$pagination = new Pagination( $items_count );  \n\t$pagination-\u003egetPageSize(); // 25\n\t$pagination-\u003esetPageSize( 999 );  \n}\ncatch ( PaginationRangeException $e ) \n{\n  echo $e-\u003egetMessage(); // \"Invalid Page size (max. 100)\"\n  echo $e-\u003egetCode();    // 400\n}\n```\n\n**Tweak the page sizes** with constructor parameters:\n\n```php\n$custom_page_size =  50; // default: 25\n$pagination = new Pagination( $items_count, $custom_page_size );\n\n$max_page_size    = 200; // default: 100\n$pagination = new Pagination( $items_count, $custom_page_size, $max_page_size );\n```\n\n\n\n### The PaginationFactory\n\nThe **PaginationFactory** constructor also accepts instances of `Countable`, `Traversable` or `arrays`, so you won't have to count the items yourself. The second parameter may be a page number *integer* or an *array* with `number` and/or `size` values. \n\n```php\n\u003c?php\nuse Germania\\Pagination\\PaginationFactory;\n\n// Optinally set default page size\n$factory = new PaginationFactory;\n$factory = new PaginationFactory( 25 );\n\n// Most simple: just integers\n$items_count = 65;\n$choose_page = 2;\n\n// Create Pagination instance:\n$pagination = $factory( $items_count, $choose_page );\n```\n\n**Creation from array** is useful when working with query parameters such as `$_GET['page']`\n\n```php\n// Both elements are optional.\n$pagination = $factory( $items_count, [\n\t'number' =\u003e 2, // default: 0\n  'size'   =\u003e 20\n]);\n\n// User Input\n$pagination = $factory( $items_count, $_GET['page'] ?? [] );\n```\n\n\n\n\n### The PaginationIterator\n\nLimits any  `\\Traversable` iterator to the current page size, depending on the *pagination* status. The **PaginationIterator** constructor accepts your *iterator* and your *pagination* instance. It is also `\\Countable` to count the numbers of items shown on the current page.\n\n```php\n\u003c?php\nuse Germania\\Pagination\\PaginationIterator;\n\n// Have your pagination at hand...\n$pagination = ...\n$pagination-\u003esetCurrent(2);\n\n// Setup something really big\n$collection = new MyHugeIterator( $thousand_items );\n\n$paginated_collection = new PaginationIterator( $collection, $pagination );\necho count( $paginated_collection ); // 25\n\nforeach( $paginated_collection as $item):\n  // loop: 25 items on page 2\nendforeach;\n```\n\n#### Which Iterator is used?\n\nDepending on the *pagination* status, *PaginationIterator's* inner iterator used in the *foreach* loop is either `\\LimitIterator` or the `MyHugeIterator` instance itself, when pagination is not active:\n\n```php\n// this time, we do not pick a page number!\n$thousand_items = ...\n$pagination = new Pagination( count($thousand_items) );\n$pagination-\u003eisActive(); // null\n\n$collection = new MyHugeIterator( $thousand_items );\n\n$paginated_collection = new PaginationIterator( $collection, $pagination );\n$iterator = $paginated_collection-\u003egetIterator();\n\nget_class( $iterator ); // MyHugeIterator instance\n```\n\n\n\n\n### The JsonApiPaginationDecorator\n\nThis library provides a handy **JsonApiPaginationDecorator** which will generate useful information for your JSON API resource collection responses with the help of a given **\\Psr\\Http\\Message\\UriInterface** instance.\n\n#### [Meta information](https://jsonapi.org/format/#document-meta) support\n\nThe `meta` member can be used to include non-standard meta-information, such as our pagination:\n\n```php\n$pagination-\u003esetCurrent( 16 );\n$pagination-\u003esetPageSize( 10 );\n\n$links = $ja_decorator-\u003egetMeta();\n// array(\n//     numberOfPages =\u003e 23\n//     currentPage   =\u003e 16\n//     pageSize      =\u003e 10\n// )\n\n```\n\n**The result array will be empty,** when the Pagination is inactive.\n\n\n\n#### [Links object](https://jsonapi.org/format/#document-links) support\n\nThe **JSON API specs** on [fetching pagination](https://jsonapi.org/format/#fetching-pagination) proposes to use `page[number]` and `page[size]` for customizing the paged output. And it states the `links` object in a collection must use these key names, when working with pagination links:\n\n- `first`: the first page of data\n- `last`: the last page of data\n- `prev`: the previous page of data\n- `next`: the next page of data\n\nThe **JsonApiPaginationDecorator** generates this elements for you. The class is `\\JsonSerializable` as well.\n\n```php\n\u003c?php\nuse Germania\\Pagination\\JsonApiPaginationDecorator;\n\n// Prepare dependencies\n$uri = \\GuzzleHttp\\Psr7\\uri_for('http://example.com');\n$pagination = ...\n$pagination-\u003esetCurrent( 2 );\n\nnew $ja_decorator = new JsonApiPaginationDecorator( $pagination, $uri);\n\n// These are equivalent:\n$links = $ja_decorator-\u003egetLinks();\n$links = $ja_decorator-\u003ejsonSerialize();\n\n// array(\n//     first    =\u003e http://example.com/?page[number]=0\n//     last     =\u003e http://example.com/?page[number]=42\n//     previous =\u003e http://example.com/?page[number]=1\n//     next     =\u003e http://example.com/?page[number]=3\n// )\n```\n\n\n\n##### Default Query Parameters\n\nThe *JsonApiPaginationDecorator* internally calls the *withQuery* method on the PSR-7 *$uri* instance. Unfortunately, this will replace any query parameters the URI contained. Just pass any needed query parameters as 3rd constructor parameter:\n\n```php\n$params = array(\n\t'foo'  =\u003e 'bar',\n  'json' =\u003e 'cool'\n);\nnew $ja_decorator = new JsonApiPaginationDecorator( $pagination, $uri, $params);\n\n$links = $ja_decorator-\u003egetLinks();\n// array(\n//     first    =\u003e http://example.com/?page[number]=0\u0026foo=bar\u0026json=cool\n//     last     =\u003e http://example.com/?page[number]=42\u0026foo=bar\u0026json=cool\n//     previous =\u003e http://example.com/?page[number]=1\u0026foo=bar\u0026json=cool\n//     next     =\u003e http://example.com/?page[number]=3\u0026foo=bar\u0026json=cool\n// )\n```\n\n\n\n##### Custom page sizes \n\nIn case you set a custom page size (which differs from the default size), the links will get an additional `size` field:\n\n```php\n$pagination-\u003esetPageSize( 10 );\n\n$links = $ja_decorator-\u003egetLinks();\n// array(\n//     first    =\u003e http://example.com/?page[number]=0\u0026page[size]=10\n//     last     =\u003e http://example.com/?page[number]=42\u0026page[size]=10\n//     previous =\u003e http://example.com/?page[number]=1\u0026page[size]=10\n//     next     =\u003e http://example.com/?page[number]=3\u0026page[size]=10\n// )\n```\n\n\n\n##### Edge cases\n\nOn the first and last page, links like `previous` and `next` do not make sense. Their value will be *null*:\n\n```php\n$pagination = new Pagination (...);\nnew $ja_decorator = new JsonApiPaginationDecorator( $pagination, $uri);\n\n$pagination-\u003esetCurrent( 0 );\n$links = $ja_decorator-\u003egetLinks();\n// array(\n//     ...\n//     previous =\u003e null\n//     next     =\u003e http://example.com/?page[number]=1\n// )\n\n$pagination-\u003esetCurrent( 42 );\n$links = $ja_decorator-\u003egetLinks();\n// array(\n//     ...\n//     previous =\u003e http://example.com/?page[number]=41\n//     next     =\u003e null\n// )\n```\n\nWhen the pagination is not active, all values per default are *null*:\n\n```php\n$pagination = new Pagination (...);\n$pagination-\u003eisActive(); // FALSE\n\n$ja_decorator-\u003egetLinks();\n// array(\n//     first    =\u003e null\n//     last     =\u003e null\n//     previous =\u003e null\n//     next     =\u003e null\n// )\n```\n\n\n\n##### Filtering the results\n\nTo get a clean, uncluttered `links` array, you may pass a boolean *filter* flag as fourth constructor parameter: \n\n```php\n$filter = true;\nnew $ja_decorator = new JsonApiPaginationDecorator( $pagination, $uri, [], $filter);\n\n$ja_decorator-\u003egetLinks();\n// array()\n```\n\n\n\n\n\n## Issues\n\nSee [full issues list.][i0]\n\n[i0]: https://github.com/GermaniaKG/Pagination/issues\n\n\n\n## Development\n\n```bash\n$ git clone https://github.com/GermaniaKG/Pagination.git\n$ cd Pagination\n$ composer install\n```\n\n\n\n## Unit tests\n\nEither copy `phpunit.xml.dist` to `phpunit.xml` and adapt to your needs, or leave as is. Run [PhpUnit](https://phpunit.de/) test or composer scripts like this:\n\n```bash\n$ composer test\n# or\n$ vendor/bin/phpunit\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgermaniakg%2Fpagination","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgermaniakg%2Fpagination","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgermaniakg%2Fpagination/lists"}