|
| 1 | +# Caching paginator pages |
| 2 | + |
| 3 | +It is possible to cache pagination results by wrapping adapters in the shipped `CachingAdapter`. |
| 4 | +The `CachingAdapter` requires a pagination adapter, a PSR cache item pool and a unique cache-key prefix. |
| 5 | + |
| 6 | +```php |
| 7 | +use DateInterval; |
| 8 | +use Laminas\Paginator\Adapter\AdapterInterface; |
| 9 | +use Psr\Cache\CacheItemPoolInterface; |
| 10 | + |
| 11 | +final readonly class CachingAdapter implements AdapterInterface |
| 12 | +{ |
| 13 | + /** |
| 14 | + * @param AdapterInterface<TKey, TValue> $adapter |
| 15 | + * @param non-empty-string $cacheKeyPrefix |
| 16 | + */ |
| 17 | + public function __construct( |
| 18 | + private AdapterInterface $adapter, |
| 19 | + private string $cacheKeyPrefix, |
| 20 | + private CacheItemPoolInterface $cache, |
| 21 | + private DateInterval|null $ttl, |
| 22 | + ) { |
| 23 | + } |
| 24 | + |
| 25 | + // ... |
| 26 | +} |
| 27 | +``` |
| 28 | + |
| 29 | +To _manually_ create a paginator that will cache results as they are retrieved, the following would be required: |
| 30 | + |
| 31 | +```php |
| 32 | +use Laminas\Paginator\Adapter\AdapterInterface; |
| 33 | +use Laminas\Paginator\Adapter\CachingAdapter; |
| 34 | +use Laminas\Paginator\Paginator; |
| 35 | +use Psr\Cache\CacheItemPoolInterface; |
| 36 | + |
| 37 | +$adapter = new \SpecialCustomAdapter(/** With some data that needs to be cached */); |
| 38 | + |
| 39 | +// Assume we have some ready-prepared objects: |
| 40 | +assert($cachePool instanceof CacheItemPoolInterface); |
| 41 | +assert($adapter instanceof AdapterInterface); |
| 42 | + |
| 43 | +$paginator = new Paginator( |
| 44 | + new CachingAdapter( |
| 45 | + $adapter, |
| 46 | + 'my-unique-prefix', |
| 47 | + $cachePool, |
| 48 | + new DateInterval('PT30M'), |
| 49 | + ), |
| 50 | + 10, |
| 51 | + 10, |
| 52 | + 'Sliding', |
| 53 | +); |
| 54 | +``` |
| 55 | + |
| 56 | +The above example assumes that `\SpecialCustomAdapter` is an adapter that makes expensive database calls or other I/O where caching is a useful performance improvement. |
| 57 | + |
| 58 | +The cache pool argument can be any [PSR-6](https://www.php-fig.org/psr/psr-6/) implementation. |
| 59 | +[laminas-cache](https://docs.laminas.dev/laminas-cache/v4/psr6/) provides a PSR-6 implementation along with [many other libraries](https://packagist.org/providers/psr/cache-implementation). |
| 60 | + |
| 61 | +Paginator assumes that you will likely use a single cache pool for all paginators, therefore a unique key prefix is required to prevent cache-key collisions with other paginator instances used elsewhere in your application. |
| 62 | + |
| 63 | +Finally, you can also provide an optional TTL in the form of a [`DateInterval`](https://www.php.net/manual/class.dateinterval.php) object. |
| 64 | + |
| 65 | +## `PaginatorFactory` integration and setting defaults |
| 66 | + |
| 67 | +The shipped `PaginatorFactory` class is capable of decorating adapters for you, providing some configuration is in-place, thereby reducing the previous example to: |
| 68 | + |
| 69 | +```php |
| 70 | +use Laminas\Paginator\PaginatorFactory; |
| 71 | +use Psr\Container\ContainerInterface; |
| 72 | + |
| 73 | +assert($container instanceof ContainerInterface); |
| 74 | + |
| 75 | +$adapter = new \SpecialCustomAdapter(/** With some data that needs to be cached */); |
| 76 | + |
| 77 | +$factory = $container->get(PaginatorFactory::class); |
| 78 | +$paginator = $factory->withCachingAdapter($adapter, 'my-unique-prefix'); |
| 79 | +``` |
| 80 | + |
| 81 | +Using the factory assumes that a single cache item pool will be used for all paginators _(Which is why the unique prefix is necessary)_. |
| 82 | +To take advantage of the paginator factory, you must ensure that you configure the necessary services. |
| 83 | +The following example assumes that you are using [Laminas Service Manager](https://docs.laminas.dev/laminas-servicemanager) for dependency injection. |
| 84 | + |
| 85 | +```php |
| 86 | +return [ |
| 87 | + // Laminas Service Manager Configuration: |
| 88 | + 'dependencies' => [ |
| 89 | + 'factories' => [ |
| 90 | + 'PaginatorCachePool' => \SomeFactoryThatWillProduceACacheItemPoolInterface::class, |
| 91 | + ], |
| 92 | + ], |
| 93 | + |
| 94 | + // Telling the paginator factory which "Service" to pull from the container: |
| 95 | + 'paginator' => [ |
| 96 | + 'defaultCache' => 'PaginatorCachePool', |
| 97 | + 'defaultCacheTTL' => 'PT30M', |
| 98 | + ], |
| 99 | +]; |
| 100 | +``` |
| 101 | + |
| 102 | +Further information: |
| 103 | + |
| 104 | +- [Custom Paginator Adapters](./advanced.md#custom-data-source-adapters) |
| 105 | +- [More information on writing factories with Laminas Service Manager](https://docs.laminas.dev/laminas-servicemanager/v4/configuring-the-service-manager/#factories) |
| 106 | +- [Using Laminas Cache as a PSR-6 Cache Pool](https://docs.laminas.dev/laminas-cache/v4/psr6/) |
| 107 | +- [The PSR-6 Specification](https://www.php-fig.org/psr/psr-6/) |
0 commit comments