Pagination¶
List methods return a page object rather than a plain array. Both page types implement \Countable and \IteratorAggregate, so a foreach over the result walks every page automatically, fetching further pages lazily under the client throttle.
CursorPage¶
Pennylane\Sdk\Pagination\CursorPage (generic over the item type T). Used by every list endpoint of the Company API, and most of the Firm API.
The API cursor does not encode filter or sort parameters, so nextPage() re-sends the original parameters together with the new cursor.
Public surface¶
| Member | Type | Description |
|---|---|---|
items |
list<T> |
Items on this page only. |
hasMore |
bool |
Whether a further page exists. |
nextCursor |
?string |
Cursor to request the next page, or null on the last page. |
included |
?list<mixed> |
Side loaded records from the experimental include parameter, when the response carries an included key. null otherwise. |
nextPage() |
?CursorPage<T> |
Fetches the next page, or null on the last page (when hasMore is false or nextCursor is null). |
iterPages() |
\Generator<int, CursorPage<T>> |
Iterates over the pages themselves, starting with this one. |
getIterator() |
\Generator<int, T> |
Iterates over the items of every page, fetching pages lazily. This is what a foreach on the page calls. |
count() |
int |
Number of items on THIS page only, not the total across all pages. |
Iteration semantics¶
$page = $client->customerInvoices->list();
// Walks every page: fetches page 2, 3, ... lazily as the loop reaches the end of each page.
foreach ($page as $invoice) {
echo $invoice->id . "\n";
}
// A second foreach on the SAME $page object walks the items again from the
// first page: getIterator() is a fresh generator each time it is called, and
// $page->items always holds the first page's items, so nothing is skipped or
// re-fetched from the network for that first page. Further pages ARE
// re-fetched over the network on each new iteration, since pages are not cached.
foreach ($page as $invoice) {
echo $invoice->id . "\n";
}
For page level control, use items, nextPage() or iterPages() instead of the flattening foreach:
$page = $client->customerInvoices->list();
foreach ($page->iterPages() as $onePage) {
echo 'Page with ' . $onePage->count() . " items, hasMore = " . var_export($onePage->hasMore, true) . "\n";
foreach ($onePage->items as $invoice) {
echo $invoice->id . "\n";
}
}
NumberedPage¶
Pennylane\Sdk\Pagination\NumberedPage (generic over the item type T). Only three Firm API endpoints use this scheme: companies, fiscalYears and trialBalance. A response missing total_pages or current_page is treated as a single page.
Public surface¶
| Member | Type | Description |
|---|---|---|
items |
list<T> |
Items on this page only. |
totalPages |
?int |
Total number of pages, or null if the response omitted it. |
currentPage |
?int |
Current page number, or null if the response omitted it. |
hasMore() |
bool |
true when both totalPages and currentPage are known and currentPage < totalPages. |
nextPage() |
?NumberedPage<T> |
Fetches the next page, or null when hasMore() is false. |
iterPages() |
\Generator<int, NumberedPage<T>> |
Iterates over the pages themselves, starting with this one. |
getIterator() |
\Generator<int, T> |
Iterates over the items of every page, fetching pages lazily. |
count() |
int |
Number of items on THIS page only. |
Note the asymmetry with CursorPage: hasMore is a property there, hasMore() is a method here, because it is derived from totalPages and currentPage rather than read directly off the response.
$firm = new Pennylane\Sdk\PennylaneFirm();
$page = $firm->companies->list();
foreach ($page as $company) {
echo $company->id . "\n";
}