Pagination et filtrage¶
Pagination par curseur (presque partout)¶
Les endpoints de liste renvoient une CursorPage. La façon la plus simple de l'utiliser : itérer avec foreach, et laisser le SDK récupérer les pages suivantes de façon paresseuse, sous la régulation de débit du client.
foreach ($client->customerInvoices->list(limit: 100) as $invoice) {
// ... parcourt TOUTES les pages de façon transparente
}
Pour contrôler les pages vous-même :
$page = $client->customerInvoices->list(limit: 100);
$page->items; // éléments de la page courante uniquement
$page->hasMore; // indique si une page suivante existe
$page->nextCursor; // curseur opaque pour la page suivante
$nextPage = $page->nextPage(); // ou null sur la dernière page
foreach ($page->iterPages() as $page) { // page par page
echo count($page->items) . PHP_EOL;
}
limit accepte des valeurs de 1 à 100 (la valeur par défaut de l'API est 20). Moins de requêtes avec limit: 100 signifie des lectures en masse plus rapides sous la limite de débit.
Les filtres ne sont pas encodés dans le curseur
Lorsque vous paginez une requête filtrée, l'API exige le même filter et le même sort à chaque requête de page. Le SDK s'en charge pour vous dans nextPage() et pendant l'itération.
Pagination par numéro de page (quelques endpoints Firm)¶
Trois endpoints de la Firm API (companies, fiscalYears, trialBalance) paginent avec page et perPage plutôt qu'avec un curseur. L'expérience reste la même :
foreach ($firm->companies->list(perPage: 50) as $company) {
// ...
}
Ces endpoints renvoient une NumberedPage, avec les propriétés totalPages et currentPage, et une méthode hasMore().
Filtrage¶
Le paramètre filter est une liste de conditions. Construisez-le avec les fonctions d'aide statiques typées de Filter :
use Pennylane\Sdk\Filter;
$client->customerInvoices->list(filter: [
Filter::gte('date', '2026-01-01'),
Filter::lt('date', '2026-07-01'),
Filter::eq('status', 'upcoming'),
Filter::in('customer_id', [42, 43]),
]);
Fonctions disponibles : eq, notEq, lt, lte, gt, gte, in, notIn, et where(field, operator, value) pour tout le reste. Les valeurs peuvent être des chaînes, des entiers, des booléens, des \DateTimeInterface ou null ; les montants doivent être des chaînes numériques, jamais des flottants.
Opérateurs sur le fil
lte() et gte() sont des noms de confort : sur le fil, l'API attend lteq et gteq. Le SDK les encode pour vous, vous n'écrivez donc jamais l'opérateur du fil vous-même.
Les champs et opérateurs pris en charge par chaque endpoint sont listés dans la référence officielle, endpoint par endpoint.
Vous pouvez aussi passer une chaîne JSON brute, ou un tableau de la forme ['field' => ..., 'operator' => ..., 'value' => ...], si vous en avez déjà un ; le SDK l'envoie tel quel.
Tri¶
$client->customerInvoices->list(sort: '-date'); // par date décroissante
$client->customerInvoices->list(sort: 'id'); // par id croissant
Depuis les évolutions de l'API de 2026, le tri par défaut est -id (les plus récents en premier) sur tous les endpoints.
Chargement conjoint avec include¶
Certains endpoints de liste prennent en charge un paramètre expérimental include pour intégrer des enregistrements liés en un seul appel :
$page = $client->customerInvoices->list(include: 'invoice_lines');
$page->included; // liste brute des enregistrements chargés conjointement