Zur Dokumentation springen
PHP

Paginierung

Eine Seite, alle Seiten oder ein Eintrag nach dem anderen, bei jeder Liste mit Seiten.

list, listAll und iterate

Jede Liste mit Seiten hat drei Methoden. list holt eine Seite und gibt eine OpenEmail\Result\Page zurück. listAll folgt dem Cursor durch alle Seiten und gibt ein einziges Array zurück. iterate durchläuft dieselben Seiten Eintrag für Eintrag und gibt einen Generator zurück, der die nächste Seite erst holt, wenn Sie dort ankommen. Alle drei nehmen die Filter der Liste, limit:, cursor: und apiKey: entgegen.

three_ways.php
$page = $client->emails->list(status: 'failed', limit: 50); foreach ($page as $email) {    echo $email['id'], ' ', $email['lastError'] ?? '', PHP_EOL;} $failures = $client->emails->listAll(status: 'failed'); foreach ($client->emails->iterate(status: 'failed') as $email) {    echo $email['id'], PHP_EOL;} echo count($failures), ' ', $page->hasMore ? 'more to come' : 'that is all', PHP_EOL;

Dieselben drei Namen wiederholen sich überall, wo ein Namespace mehr als eine Liste hat, benannt nach der Liste, die sie durchlaufen: listEvents, listAllEvents und iterateEvents bei emails, listDeliveries, listAllDeliveries und iterateDeliveries bei webhooks und so weiter.

OpenEmail\Result\Page

itemsarray
Die Zeilen dieser Seite, aus dem `data`-Umschlag der API herausgelöst, jede ein assoziatives Array. Leer, wenn die Seite nichts enthält.
hasMorebool
Ob eine weitere Seite folgt. Sendet die API kein `hasMore`, ist es genau dann true, wenn es einen `nextCursor` gibt.
nextCursorstring or null
Was Sie für die nächste Seite als `cursor:` zurückgeben, und null auf der letzten.

Eine Seite ist unveränderlich: Ihre Eigenschaften sind readonly. Sie ist außerdem IteratorAggregate und Countable, foreach ($page as $item) durchläuft also ihre Zeilen, und count($page) zählt sie.

Ein Generator

iterate fordert nichts an, bis Sie mit dem Durchlauf beginnen, und es fordert die nächste Seite erst an, wenn jeder Eintrag der aktuellen geliefert wurde. Alles, was früh aufhört, stoppt also auch die Anfragen: break beendet den Durchlauf, und ebenso die Rückkehr aus der Funktion, die die Schleife enthält.

generator.php
$latest = []; foreach ($client->emails->iterate(status: 'failed', limit: 100) as $email) {    $latest[] = $email;     if (count($latest) === 10) {        break;    }} $invoice = null; foreach ($client->emails->iterate(status: 'failed') as $email) {    if (($email['tags']['invoice'] ?? null) === 'inv_2026_09_4192') {        $invoice = $email;         break;    }} echo count($latest), ' ', $invoice['id'] ?? 'not found', PHP_EOL;

Alles, was jeden Eintrag braucht, etwa iterator_to_array() auf dem Generator aufgerufen, liest jede Seite, bevor es zurückkehrt, so wie listAll.

Ein Generator lässt sich nur einmal durchlaufen. Ein zweiter Durchlauf wirft, rufen Sie also iterate erneut auf, wenn Sie die Einträge noch einmal brauchen, oder behalten Sie die Einträge statt des Generators.

Von einem Cursor aus fortsetzen

Ein Cursor ist opak. Behalten Sie den nextCursor der zuletzt gelesenen Seite und übergeben Sie ihn als cursor:, um dort weiterzumachen, in einer späteren Anfrage oder in einem anderen Prozess. listAll und iterate nehmen ebenfalls cursor: entgegen und beginnen ihren Durchlauf danach.

resume.php
$firstPage = $client->emails->list(status: 'failed', limit: 25);$saved = $firstPage->nextCursor; if ($saved !== null) {    $rest = $client->emails->listAll(status: 'failed', cursor: $saved);    echo count($rest), PHP_EOL;}

Ein Cursor gehört zu der Liste und den Filtern, aus denen er stammt, senden Sie also dieselben Filter mit. Einen Cursor, den die Liste nicht zuordnen kann, lehnt sie mit invalid_cursor ab, und dann hilft nur, ohne Cursor neu zu beginnen.

limit:

limit: ist die Größe jeder Seite, keine Gesamtzahl. Bei list ist es die Anzahl der zurückgegebenen Zeilen. Bei listAll und iterate ist es die Anzahl, die jede Anfrage anfordert, ein größerer Wert bedeutet also weniger Roundtrips für dieselben Zeilen. Jede Liste hat ihren eigenen Bereich und Standardwert, meist 1 bis 100 mit 25, wenn Sie nichts senden, und ein Wert außerhalb des Bereichs wird abgelehnt statt begrenzt. Die Referenz jeder Liste nennt ihren Bereich.

Wann ein Durchlauf endet

  • Wenn eine Seite meldet, dass hasMore false ist.
  • Wenn eine Seite keinen nextCursor trägt, denn eine Seite, die mehr behauptet und dabei keinen Cursor nennt, würde endlos kreisen.
  • Wenn die API einen Cursor zurückgibt, dem der Durchlauf schon gefolgt ist, aus demselben Grund.

Jede Seite ist ein GET und wird daher wie jeder Lesevorgang für sich wiederholt, bevor etwas geworfen wird. Ein Fehlschlag, der die Wiederholungen übersteht, wird aus listAll heraus geworfen, und die bereits geholten Einträge werden verworfen. Bei iterate wurden die Einträge der früheren Seiten zu diesem Zeitpunkt schon geliefert. Sorgen Sie also dafür, dass die Schleife gefahrlos zweimal laufen kann, oder blättern Sie mit list und behalten Sie jeden nextCursor, damit ein zweiter Versuch dort beginnen kann, wo der erste aufgehört hat.

Threads und Entwürfe

threads->list und drafts->list blättern samt ihren listAll und iterate mit pageToken und nextPageToken der API statt mit einem Cursor. Der Client verbirgt den Unterschied: Übergeben Sie das Token als cursor: und lesen Sie es aus nextCursor.

page_token.php
$page = $client->threads->list(folder: 'inbox', limit: 50);$later = $page->hasMore ? $client->threads->list(folder: 'inbox', limit: 50, cursor: $page->nextCursor) : null; echo count($page), ' ', $later === null ? 0 : count($later), PHP_EOL;

Der Server bietet ein Token an, wann immer eine Seite voll zurückkommt. hasMore kann also auf einer Seite true sein, die sich als die letzte herausstellt, und der nächste Aufruf gibt dann keine Einträge zurück.

Seiten mit zusätzlichen Feldern

Einige Listen antworten mit mehr als nur Zeilen und geben statt Page ein eigenes Objekt aus OpenEmail\Result zurück. Jedes ist unveränderlich, IteratorAggregate über seine Zeilen und Countable.

MethodeGibt zurückWas sie ergänzt
addresses->listAddressBookPageaddresses statt items, dazu unrestricted und domains, mit hasMore und nextCursor.
addresses->listAllAddressBookJede Adresse in addresses, mit unrestricted und domains so, wie die letzte Seite sie gemeldet hat. Es ist das einzige listAll, das das ganze Adressbuch statt eines Arrays zurückgibt. addresses->iterate übergibt nur die Adressen.
contacts->listPeoplePeoplePageseen, false, wenn der Schlüssel die in Mails gesehenen Adressen nicht lesen kann. listAllPeople und iteratePeople geben nur die Personen zurück.
tempMail->listMessagesTempMessagesPageexpiresAt, wann der Posteingang abläuft. listAllMessages und iterateMessages geben nur die Nachrichten zurück.
templates->listSendsTemplateSendsNach Seitennummer statt nach Cursor geblättert: items, total, page und pageSize. Fordern Sie die nächste Seite mit page: an.
emails->sendBatchBatchResultKeine Seite: items, ein Eintrag für jede gesendete Nachricht, mit den Zählern sent und failed.

Listen, die das Array der API zurückgeben

Einige Listen blättern per Offset, per Seitennummer oder mit einem eigenen numerischen Cursor und geben den dekodierten Body so zurück, wie er kam, als Array mit data statt als Page. Sie haben kein listAll und kein iterate, Sie blättern sie also selbst.

MethodeBlättert mitWas zurückkommt
exports->listlimit: und offset:data, total und hasMore.
imports->listFailuresafter: und limit:data und nextCursor, ein Integer, den Sie als after: zurückgeben und der auf der letzten Seite null ist.
subscriptions->list und subscriptions->listDomainslimit: und offset:data, total, counts und hasMore.
billing->listInvoicespage: und limit:data, total, page, limit, hasMore und metered.
offset_paging.php
$offset = 0; do {    $batch = $client->subscriptions->list(status: 'active', limit: 50, offset: $offset);     foreach ($batch['data'] as $row) {        echo $row['senderEmail'], ' ', $row['total'], PHP_EOL;    }     $offset += count($batch['data']);} while ($batch['hasMore'] && $batch['data'] !== []);

Eine Liste ganz ohne Seiten, etwa languages->list, labels->listColors oder roles->listPermissions, gibt ihre Zeilen direkt als einfache Liste zurück.