Skip to content

Commit 6151dd4

Browse files
authored
Merge pull request #92 from gsteel/v3/migration-guide
Finish Migration Guide, Caching Docs and v3 Release Preparation
2 parents aadcf2d + b5f1072 commit 6151dd4

File tree

16 files changed

+826
-320
lines changed

16 files changed

+826
-320
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,11 @@ unused-ci: vendor/bin/composer-unused
139139

140140
rector: ## Run Rector and show the diff
141141
@$(call MK_INFO,"Checking for syntax consistency with rector")
142-
@docker run $(DOCKER_PHP) tools/rector/vendor/bin/rector process --dry-run -vv -c tools/rector/rector.php
142+
@docker run $(DOCKER_PHP) tools/rector/vendor/bin/rector process --dry-run -c tools/rector/rector.php
143143
.PHONY: rector
144144

145145
rector-ci: ## Run Rector and show the diff in GitHub format for CI
146-
tools/rector/vendor/bin/rector process --dry-run --output-format=github -vv -c tools/rector/rector.php
146+
tools/rector/vendor/bin/rector process --dry-run --output-format=github -c tools/rector/rector.php
147147
.PHONY: rector
148148

149149
rector-fix: ## Apply Rector changes

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@
3939
"laminas/laminas-cache": "^4.1",
4040
"laminas/laminas-cache-storage-adapter-memory": "^3.1",
4141
"laminas/laminas-coding-standard": "^3.1.0",
42-
"lcobucci/clock": "^3.3",
43-
"phpunit/phpunit": "^11.5.43",
42+
"lcobucci/clock": "^3.3.1",
43+
"phpunit/phpunit": "^11.5.45",
4444
"psalm/plugin-phpunit": "^0.19.5",
4545
"vimeo/psalm": "^6.13.1"
4646
},

composer.lock

Lines changed: 121 additions & 108 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/book/v3/advanced.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ Take a look at the packaged adapters for ideas of how you might go about impleme
4949

5050
### Registering Your Adapter with the Plugin Manager
5151

52-
> Available since version 2.10.0.
53-
5452
If you want to register your adapter with the `Laminas\Pagiantor\AdapterPluginManager`, you can do so via configuration.
5553
The "paginators" configuration key can contain [standard laminas-servicemanager-style configuration](https://docs.laminas.dev/laminas-servicemanager/configuring-the-service-manager/).
5654

docs/book/v3/application-integration/stand-alone.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ foreach ($paginator as $item) {
9090
}
9191
```
9292

93-
Retrieving the [current status data of the paginator](../usage.md#listing-of-properties):
93+
Retrieving the [current status data of the paginator](../usage.md#inspecting-paginator-state):
9494

9595
```php
9696
var_dump($paginator->getPages()->previous); // 1

docs/book/v3/caching.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
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/)
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Migrating from Version 2 to Version 3
2+
3+
Version 3 of Laminas Paginator contains several backward incompatible changes.
4+
5+
## New Features
6+
7+
### Laminas Service Manager v4 Support
8+
9+
`laminas-paginator` new requires `laminas-servicemanager` version 4, therefore allowing `psr/container` 2.0 installation.
10+
11+
### Re-worked, Optional Caching with `psr/cache`
12+
13+
With the [removal of caching](#caching) from the paginator itself, it is now possible to decorate adapters as needed with the `CachingAdapter`:
14+
15+
```php
16+
use Laminas\Paginator\Adapter\ArrayAdapter;
17+
use Laminas\Paginator\Adapter\CachingAdapter;
18+
use Laminas\Paginator\Paginator;
19+
20+
$paginator = new Paginator(
21+
new CachingAdapter(
22+
new ArrayAdapter($someData),
23+
'my-unique-prefix',
24+
$someCacheItemPoolInterface,
25+
),
26+
);
27+
```
28+
29+
[Further Documentation](../caching.md)
30+
31+
## Bug Fixes & General Improvements
32+
33+
- Native parameter, property and return types have been added throughout the code base
34+
- It is now possible to paginate associative arrays, or any type of iterable with string keys. Type inference for keys and values is retained.
35+
- Type inference has been drastically improved for a more convenient developer experience. We strongly suggest usage of Psalm or PHPStan to benefit from these improvements.
36+
37+
## Feature Removal
38+
39+
### Caching
40+
41+
The caching features of the main Paginator class have been removed.
42+
This means the following constants and methods of `Laminas\Paginator\Paginator` no longer exist:
43+
44+
- `CACHE_TAG_PREFIX` constant
45+
- `setCache()`
46+
- `setCacheEnabled()`
47+
- `clearPageItemCache()`
48+
- `getPageItemCache()`
49+
- `cacheEnabled()`
50+
51+
### `laminas-view` integration
52+
53+
`Laminas\Paginator\Paginator` was unnecessarily, tightly coupled to Laminas View.
54+
Because paginator is conceptually independent of a specific templating implementation, expect stand-alone integrations in the future.
55+
The removal of Laminas view integration resulted in the following changes to `Laminas\Paginator\Paginator`:
56+
57+
- `Laminas\Paginator\Paginator` no longer implements the `Stringable` interface
58+
- The following methods have been removed:
59+
- `__toString()`
60+
- `getView()`
61+
- `setView()`
62+
- `render()`
63+
64+
### Removal of Un-documented Filtering Feature
65+
66+
Previously, paginator allowed users to provide a `Laminas\Filter\FilterInterface` that would be used to filter/mutate the result set returned by adapters.
67+
This feature has been removed.
68+
It is unlikely the feature was widely used, and it had questionable merit because it would break the guarantees that a page of 10 items, would indeed contain 10 items.
69+
70+
The following methods have been removed from `Laminas\Paginator\Paginator`:
71+
72+
- `getFilter()`
73+
- `setFilter()`
74+
75+
### Removal of the `ScrollingStylePluginManager`
76+
77+
Generally speaking, scrolling styles are relatively simple computations.
78+
They can easily be "newed" when required.
79+
You can still refer to them by 'name', for example _'Sliding'_.
80+
81+
Along with the plugin manger, a number of static methods associated with scrolling styles were removed from `Laminas\Paginator\Paginator`:
82+
83+
- `getDefaultScrollingStyle()`
84+
- `setDefaultScrollingStyle()`
85+
- `getDefaultItemCountPerPage()`
86+
- `setDefaultItemCountPerPage()`
87+
- `setScrollingStylePluginManager()`
88+
- `getScrollingStylePluginManager()`
89+
90+
### Json encoding of Paginator Result Sets
91+
92+
The method `Laminas\Paginator\Paginator::toJson()` has been removed.
93+
It is not a paginators concern to encode the paged items to any format.
94+
If you relied on this functionality, it can be reproduced by encoding the current items yourself with `json_encode`, for example:
95+
96+
```php
97+
$json = json_encode($paginator->getCurrentItems());
98+
```
99+
100+
### Removal of "Global Config" via Static Properties
101+
102+
The method `Laminas\Paginator\Paginator::setGlobalConfig()` has been removed.
103+
To create pagers with consistent and centralised configuration defaults, use the [newly introduced `PaginatorFactory`](../configuration.md#the-paginator-factory-service).
104+
105+
### Removal of Unused Exception Types
106+
107+
The following exceptions no longer exist:
108+
109+
- `Laminas\Paginator\Adapter\Exception\RuntimeException`
110+
- `Laminas\Paginator\Adapter\Exception\UnexpectedValueException`
111+
- `Laminas\Paginator\Exception\UnexpectedValueException`
112+
113+
### Laminas MVC Module Manager Support
114+
115+
The `Module` class has been removed.
116+
It is possible to use the shipped `ConfigProvider` to ensure that the library is correctly configured for use with the application Service Manager.
117+
118+
### Removal of the `Factory` class
119+
120+
The class `Laminas\Paginator\Factory` has been removed.
121+
Its conceptual functionality is replaced with the `Laminas\Paginator\PaginatorFactory` class which is [documented in detail here](../configuration.md#the-paginator-factory-service).

docs/book/v3/usage.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ return [
4848
];
4949
```
5050

51-
With the above route (and using [laminas-mvc](https://docs.laminas.dev/laminas-mvc/) controllers), you might set the current page number in your controller action like so:
51+
With the above route, in a [Mezzio](https://docs.mezzio.dev) application, you might set the current page number in your middleware like so:
5252

5353
```php
54-
$paginator->setCurrentPageNumber($this->params()->fromRoute('page'));
54+
$paginator->setCurrentPageNumber((int) $request->getAttribute('page'));
5555
```
5656

5757
Now we have a paginator filled with data, and the current page number is known, we can iterate over the paginated items:
@@ -277,3 +277,27 @@ $paginator->getPages(new ScrollingStyle());
277277
```
278278

279279
For further details on the other available options; see the [Configuration chapter](configuration.md).
280+
281+
## Inspecting Paginator State
282+
283+
The paginator keeps track of its current position and provides a number of methods to retrieve information about its state:
284+
285+
```php
286+
assert($pager instanceof Laminas\Paginator\Paginator);
287+
288+
printf("The current page number is %d\n", $pager->getCurrentPageNumber());
289+
printf("The current page contains %d items\n", $pager->getCurrentItemCount());
290+
printf("In total there are %d items\n", $pager->getTotalItemCount());
291+
292+
$pagesResult = $pager->getPages();
293+
294+
printf("The first page number is %d\n", $pagesResult->first);
295+
printf("The first page number in range is %d\n", $pagesResult->firstPageInRange);
296+
printf("The last page number is %d\n", $pagesResult->last);
297+
printf("The last page number in range is %d\n", $pagesResult->lastPageInRange);
298+
printf("The next page number is %s\n", $pagesResult->next ?? 'NONE');
299+
printf("The previous page number is %s\n", $pagesResult->previous ?? 'NONE');
300+
printf("The total number of pages is %d\n", $pagesResult->pageCount);
301+
```
302+
303+
The `Laminas\Paginator\Pages` value object retrieved from `$pager->getPages()` provides all the information needed to create a page navigation user interface.

mkdocs.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ nav:
88
- Usage: v3/usage.md
99
- Configuration: v3/configuration.md
1010
- "Advanced Usage": v3/advanced.md
11+
- "Caching Paged Result Sets": v3/caching.md
1112
- 'Application Integration':
1213
- 'Stand-Alone': v3/application-integration/stand-alone.md
14+
- 'Migration':
15+
- 'From v2 to v3': v3/migration/from-v2-to-v3.md
1316
- v2:
1417
- Introduction: v2/intro.md
1518
- Installation: v2/installation.md

psalm.xml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
findUnusedCode="true"
99
findUnusedBaselineEntry="true"
1010
findUnusedPsalmSuppress="true"
11+
ensureOverrideAttribute="false"
1112
>
1213
<projectFiles>
1314
<directory name="src"/>
@@ -18,12 +19,6 @@
1819
</projectFiles>
1920

2021
<issueHandlers>
21-
<MissingOverrideAttribute>
22-
<errorLevel type="suppress">
23-
<directory name="src" />
24-
<directory name="test" />
25-
</errorLevel>
26-
</MissingOverrideAttribute>
2722
</issueHandlers>
2823
<plugins>
2924
<pluginClass class="Psalm\PhpUnitPlugin\Plugin"/>

0 commit comments

Comments
 (0)