https://github.com/germaniakg/pagination
Pagination Calculator for large collections. Good for JsonAPI and paginated output.
https://github.com/germaniakg/pagination
arrays jsonapi paginated-results pagination traversable
Last synced: about 1 year ago
JSON representation
Pagination Calculator for large collections. Good for JsonAPI and paginated output.
- Host: GitHub
- URL: https://github.com/germaniakg/pagination
- Owner: GermaniaKG
- Created: 2019-03-14T11:31:47.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2022-05-30T14:22:55.000Z (about 4 years ago)
- Last Synced: 2025-02-08T20:12:44.345Z (over 1 year ago)
- Topics: arrays, jsonapi, paginated-results, pagination, traversable
- Language: PHP
- Homepage:
- Size: 38.1 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Germania KG · Pagination
[](https://packagist.org/packages/germania-kg/pagination)
[](https://packagist.org/packages/germania-kg/pagination)
[](https://travis-ci.org/GermaniaKG/Pagination)
[](https://scrutinizer-ci.com/g/GermaniaKG/Pagination/?branch=master)
[](https://scrutinizer-ci.com/g/GermaniaKG/Pagination/?branch=master)
[](https://scrutinizer-ci.com/g/GermaniaKG/Pagination/build-status/master)
## Installation with Composer
```bash
$ composer require germania-kg/pagination
```
## Overview
**Pagination:**
Page numbering made easy! Supports *current, next, previous, first* and *last* page numbers as well as *number of pages* and customizable *page sizes*.
**PaginationFactory:**
Callable class for creating a *Pagination* instance. Works great with `$_GET['page']`
**PaginationIterator:**
Limits your *Traversables* according to the *Pagination* status. Useful for paginated **JSON API** resources.
**JsonApiPaginationDecorator:**
Create useful `links` and `meta` information for your **JSON API** resource collection.
## Usage
### The Pagination class
Just 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.
```php
getPagesCount(); // 4, with 25 items each
$pagination->getFirst(); // 0
$pagination->getLast(); // 3
```
#### Pagination status
Right after instantiation, no page was picked by the user. Hence, the *Pagination* is then considered *inactive*.
Please 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->getCurrent() === null` .
```php
$pagination->isActive(); // FALSE
$pagination->getCurrent(); // null
$pagination->getPrevious(); // null
$pagination->getNext(); // null
```
It first needs a *setCurrent* call to become *active*:
#### Setting the current page
```php
use Germania\Pagination\PaginationRangeException;
try {
$pagination->setCurrent( 1 );
$pagination->isActive(); // TRUE
$pagination->getCurrent(); // 1
$pagination->getPrevious(); // null
$pagination->getNext(); // 2
}
catch ( PaginationRangeException $e )
{
echo $e->getMessage(); // "Invalid Page number"
echo $e->getCode(); // 400
}
```
#### Setting the page size
Whilst the default number of items on a page is 25, you may set another size—up to 100 per default:
```php
use Germania\Pagination\PaginationRangeException;
try {
$pagination = new Pagination( $items_count );
$pagination->getPageSize(); // 25
$pagination->setPageSize( 999 );
}
catch ( PaginationRangeException $e )
{
echo $e->getMessage(); // "Invalid Page size (max. 100)"
echo $e->getCode(); // 400
}
```
**Tweak the page sizes** with constructor parameters:
```php
$custom_page_size = 50; // default: 25
$pagination = new Pagination( $items_count, $custom_page_size );
$max_page_size = 200; // default: 100
$pagination = new Pagination( $items_count, $custom_page_size, $max_page_size );
```
### The PaginationFactory
The **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.
```php
2, // default: 0
'size' => 20
]);
// User Input
$pagination = $factory( $items_count, $_GET['page'] ?? [] );
```
### The PaginationIterator
Limits 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.
```php
setCurrent(2);
// Setup something really big
$collection = new MyHugeIterator( $thousand_items );
$paginated_collection = new PaginationIterator( $collection, $pagination );
echo count( $paginated_collection ); // 25
foreach( $paginated_collection as $item):
// loop: 25 items on page 2
endforeach;
```
#### Which Iterator is used?
Depending 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:
```php
// this time, we do not pick a page number!
$thousand_items = ...
$pagination = new Pagination( count($thousand_items) );
$pagination->isActive(); // null
$collection = new MyHugeIterator( $thousand_items );
$paginated_collection = new PaginationIterator( $collection, $pagination );
$iterator = $paginated_collection->getIterator();
get_class( $iterator ); // MyHugeIterator instance
```
### The JsonApiPaginationDecorator
This 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.
#### [Meta information](https://jsonapi.org/format/#document-meta) support
The `meta` member can be used to include non-standard meta-information, such as our pagination:
```php
$pagination->setCurrent( 16 );
$pagination->setPageSize( 10 );
$links = $ja_decorator->getMeta();
// array(
// numberOfPages => 23
// currentPage => 16
// pageSize => 10
// )
```
**The result array will be empty,** when the Pagination is inactive.
#### [Links object](https://jsonapi.org/format/#document-links) support
The **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:
- `first`: the first page of data
- `last`: the last page of data
- `prev`: the previous page of data
- `next`: the next page of data
The **JsonApiPaginationDecorator** generates this elements for you. The class is `\JsonSerializable` as well.
```php
setCurrent( 2 );
new $ja_decorator = new JsonApiPaginationDecorator( $pagination, $uri);
// These are equivalent:
$links = $ja_decorator->getLinks();
$links = $ja_decorator->jsonSerialize();
// array(
// first => http://example.com/?page[number]=0
// last => http://example.com/?page[number]=42
// previous => http://example.com/?page[number]=1
// next => http://example.com/?page[number]=3
// )
```
##### Default Query Parameters
The *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:
```php
$params = array(
'foo' => 'bar',
'json' => 'cool'
);
new $ja_decorator = new JsonApiPaginationDecorator( $pagination, $uri, $params);
$links = $ja_decorator->getLinks();
// array(
// first => http://example.com/?page[number]=0&foo=bar&json=cool
// last => http://example.com/?page[number]=42&foo=bar&json=cool
// previous => http://example.com/?page[number]=1&foo=bar&json=cool
// next => http://example.com/?page[number]=3&foo=bar&json=cool
// )
```
##### Custom page sizes
In case you set a custom page size (which differs from the default size), the links will get an additional `size` field:
```php
$pagination->setPageSize( 10 );
$links = $ja_decorator->getLinks();
// array(
// first => http://example.com/?page[number]=0&page[size]=10
// last => http://example.com/?page[number]=42&page[size]=10
// previous => http://example.com/?page[number]=1&page[size]=10
// next => http://example.com/?page[number]=3&page[size]=10
// )
```
##### Edge cases
On the first and last page, links like `previous` and `next` do not make sense. Their value will be *null*:
```php
$pagination = new Pagination (...);
new $ja_decorator = new JsonApiPaginationDecorator( $pagination, $uri);
$pagination->setCurrent( 0 );
$links = $ja_decorator->getLinks();
// array(
// ...
// previous => null
// next => http://example.com/?page[number]=1
// )
$pagination->setCurrent( 42 );
$links = $ja_decorator->getLinks();
// array(
// ...
// previous => http://example.com/?page[number]=41
// next => null
// )
```
When the pagination is not active, all values per default are *null*:
```php
$pagination = new Pagination (...);
$pagination->isActive(); // FALSE
$ja_decorator->getLinks();
// array(
// first => null
// last => null
// previous => null
// next => null
// )
```
##### Filtering the results
To get a clean, uncluttered `links` array, you may pass a boolean *filter* flag as fourth constructor parameter:
```php
$filter = true;
new $ja_decorator = new JsonApiPaginationDecorator( $pagination, $uri, [], $filter);
$ja_decorator->getLinks();
// array()
```
## Issues
See [full issues list.][i0]
[i0]: https://github.com/GermaniaKG/Pagination/issues
## Development
```bash
$ git clone https://github.com/GermaniaKG/Pagination.git
$ cd Pagination
$ composer install
```
## Unit tests
Either 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:
```bash
$ composer test
# or
$ vendor/bin/phpunit
```