Ajouter la pagination
Ce guide explique comment ajouter la pagination ?limit= / ?offset= à un endpoint de collection à l'aide du helper PaginationQueryParser de Nene2\Http.
Prérequis
- Un handler de collection fonctionnel (ex.
ListNotesHandler). - Le handler retourne une enveloppe JSON avec
items,limitetoffset.
Étape 1 — Appeler PaginationQueryParser::parse()
Remplacez l'extraction manuelle des paramètres de requête par le parseur. Il valide les valeurs et lance ValidationException (→ 422) si elles sont hors plage.
php
use Nene2\Http\PaginationQueryParser;
public function handle(ServerRequestInterface $request): ResponseInterface
{
$pagination = PaginationQueryParser::parse($request); // défaut : limit=20, max=100
$output = $this->useCase->execute(
new ListWidgetsInput($pagination->limit, $pagination->offset),
);
return $this->response->create([
'items' => /* mapper $output->items */,
'limit' => $output->limit,
'offset' => $output->offset,
]);
}PaginationQuery est un DTO readonly avec deux propriétés : limit: int et offset: int.
Étape 2 — Personnaliser les limites (optionnel)
Passez $defaultLimit et $maxLimit pour remplacer les valeurs par défaut (20 et 100) :
php
$pagination = PaginationQueryParser::parse($request, defaultLimit: 10, maxLimit: 50);| Paramètre | Défaut | Signification |
|---|---|---|
$defaultLimit | 20 | Utilisé quand ?limit= est absent |
$maxLimit | 100 | Valeur maximale autorisée ; retourne 422 si dépassée |
Étape 3 — Gérer l'erreur 422
PaginationQueryParser::parse() lance ValidationException quand :
limit < 1oulimit > $maxLimitoffset < 0
ErrorHandlerMiddleware mappe automatiquement ValidationException → 422 validation-failed. Aucune gestion d'erreur supplémentaire n'est nécessaire dans le handler.
Exemple de réponse 422 :
json
{
"type": "https://nene2.dev/problems/validation-failed",
"title": "Validation Failed",
"status": 422,
"detail": "The request body contains invalid values.",
"errors": [
{ "field": "limit", "message": "limit must be between 1 and 100.", "code": "out_of_range" }
]
}Fonctionnement
PaginationQueryParser::parse() lit getQueryParams() de la requête PSR-7, caste les valeurs en int, les valide et retourne un DTO PaginationQuery. Les valeurs non numériques sont castées en 0 (comportement PHP de (int)) puis interceptées par la vérification limit < 1.
Étape 4 — Utiliser PaginationResponse pour standardiser l'envelope
PaginationResponse est un DTO readonly qui construit l'envelope de liste standard :
php
use Nene2\Http\PaginationResponse;
return $this->response->create(
(new PaginationResponse(
items: array_map(fn ($item) => ['id' => $item->id, 'name' => $item->name], $output->items),
limit: $output->limit,
offset: $output->offset,
))->toArray(),
);Étape 5 — Inclure le nombre total d'enregistrements (optionnel)
Passez total quand le repository supporte une requête COUNT :
php
$total = $this->repository->countAll(); // SELECT COUNT(*) AS n FROM ...
return $this->response->create(
(new PaginationResponse(items: /* ... */, limit: $output->limit, offset: $output->offset, total: $total))->toArray(),
);Quand total est null (défaut), la clé est omise de la réponse.
Compromis :
COUNT(*)ajoute une requête par appel. Ometteztotalsi l'overhead est inacceptable et laissez les clients détecter la dernière page avecitems.length < limit.
Étape 6 — Analyser d'autres paramètres de requête avec QueryStringParser
Utilisez QueryStringParser pour les paramètres de filtrage autres que limit/offset.
php
use Nene2\Http\QueryStringParser;
$search = QueryStringParser::string($request, 'search'); // ?string
$page = QueryStringParser::int($request, 'page'); // ?int
$active = QueryStringParser::bool($request, 'is_active'); // ?bool
// Valeurs multiples séparées par des virgules : ?tags=php,lang → ['php', 'lang']
$tags = QueryStringParser::commaSeparated($request, 'tags'); // list<string>|null
// Clé répétée à la manière de PHP : ?tags[]=php&tags[]=api → ['php', 'api']
$tags = QueryStringParser::array($request, 'tags'); // list<string>|nullcommaSeparated() découpe sur les virgules, supprime les espaces et les valeurs vides, et renvoie null si le paramètre est absent ou si la liste est vide après filtrage.
array() gère les clés répétées à la manière de PHP (?key[]=v1&key[]=v2). Les implémentations PSR-7 les analysent en ['key' => ['v1', 'v2']] dans getQueryParams(). Renvoie null si la clé est absente ou si la valeur n'est pas un tableau.
Voir aussi
src/Example/Note/ListNotesHandler.php— implémentation de référence avecPaginationResponsesrc/Example/Tag/ListTagsHandler.php— deuxième exempleNene2\Http\PaginationQuery— DTO readonlyNene2\Http\PaginationQueryParser— la classe parseurNene2\Http\PaginationResponse— le DTO envelope de listeNene2\Http\QueryStringParser— helpers typés pour les autres paramètres de requête