Saltar para a documentação
PHP

Paginação

Uma página, todas as páginas ou um item de cada vez, em todas as listas paginadas.

list, listAll e iterate

Todas as listas paginadas têm três métodos. list obtém uma página e devolve uma OpenEmail\Result\Page. listAll segue o cursor por todas as páginas e devolve um único array. iterate percorre as mesmas páginas um item de cada vez e devolve um Generator, que só obtém a página seguinte quando lá chega. Os três aceitam os filtros da lista, limit:, cursor: e apiKey:.

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;

Os mesmos três nomes repetem-se sempre que um espaço de nomes tem mais do que uma lista, com o nome da lista que percorrem: listEvents, listAllEvents e iterateEvents em emails, listDeliveries, listAllDeliveries e iterateDeliveries em webhooks, e assim por diante.

OpenEmail\Result\Page

itemsarray
As linhas desta página, retiradas do envelope `data` da API, cada uma um array associativo. Vazio quando a página não contém nada.
hasMorebool
Se há outra página a seguir. Quando a API não envia `hasMore`, é true exatamente quando existe um `nextCursor`.
nextCursorstring or null
O que deve devolver como `cursor:` para obter a página seguinte, e null na última.

Uma página é imutável: as suas propriedades são readonly. É também IteratorAggregate e Countable, por isso foreach ($page as $item) percorre as suas linhas e count($page) conta-as.

Um Generator

iterate não pede nada até começar a percorrê-lo, e só pede a página seguinte depois de entregues todos os itens da atual, por isso tudo o que para mais cedo também para os pedidos: break termina o percurso, tal como sair da função que contém o ciclo.

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;

Tudo o que precise de todos os itens, como iterator_to_array() chamado sobre o Generator, lê todas as páginas antes de devolver, tal como listAll.

Um Generator só pode ser percorrido uma vez. Percorrê-lo uma segunda vez lança uma exceção, por isso chame iterate de novo quando precisar outra vez dos itens, ou guarde os itens em vez do Generator.

Retomar a partir de um cursor

Um cursor é opaco. Guarde o nextCursor da última página que leu e devolva-o como cursor: para continuar a partir daí, num pedido posterior ou noutro processo. listAll e iterate também aceitam cursor: e começam o seu percurso a seguir a ele.

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;}

Um cursor pertence à lista e aos filtros de onde veio, por isso envie os mesmos filtros com ele. Um que a lista não consiga situar é recusado com invalid_cursor, e a solução é então recomeçar sem cursor.

limit:

limit: é o tamanho de cada página, não um total. Em list é quantas linhas voltam. Em listAll e iterate é quantas cada pedido pede, por isso um valor maior significa menos idas e voltas para as mesmas linhas. Cada lista tem o seu próprio intervalo e valor predefinido, quase sempre de 1 a 100 com 25 se não enviar nenhum, e um valor fora do intervalo é recusado em vez de ajustado. A referência de cada lista indica o seu intervalo.

Quando um percurso para

  • Quando uma página diz que hasMore é false.
  • Quando uma página não traz nextCursor, já que uma página que diz haver mais sem indicar nenhum cursor ficaria em ciclo para sempre.
  • Quando a API devolve um cursor que o percurso já seguiu, pelo mesmo motivo.

Cada página é um GET, por isso é repetida por si só, como qualquer leitura, antes de se lançar o que quer que seja. Uma falha que sobreviva às repetições é lançada a partir de listAll, e os itens já obtidos são descartados. Em iterate, os itens das páginas anteriores já foram entregues nessa altura, por isso torne seguro executar duas vezes o que o ciclo faz, ou pagine com list e guarde cada nextCursor para que uma segunda tentativa possa começar onde a primeira parou.

Conversas e rascunhos

threads->list e drafts->list, com os seus listAll e iterate, paginam com o pageToken e o nextPageToken da API em vez de um cursor. O cliente esconde a diferença: passe o token como cursor: e leia-o de 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;

O servidor oferece um token sempre que uma página volta cheia, por isso hasMore pode ser true naquela que acaba por ser a última página, e a chamada seguinte não devolve então nenhum item.

Páginas que trazem mais

Algumas listas respondem com mais do que linhas, e devolvem um objeto próprio de OpenEmail\Result em vez de Page. Cada um é imutável, IteratorAggregate sobre as suas linhas e Countable.

MétodoDevolveO que acrescenta
addresses->listAddressBookPageaddresses em vez de items, mais unrestricted e domains, com hasMore e nextCursor.
addresses->listAllAddressBookTodos os endereços em addresses, com unrestricted e domains tal como a última página os indicou. É o único listAll que devolve o livro de endereços inteiro em vez de um array. addresses->iterate entrega apenas os endereços.
contacts->listPeoplePeoplePageseen, false quando a chave não consegue ler os endereços vistos no correio. listAllPeople e iteratePeople devolvem apenas as pessoas.
tempMail->listMessagesTempMessagesPageexpiresAt, o momento em que a caixa expira. listAllMessages e iterateMessages devolvem apenas as mensagens.
templates->listSendsTemplateSendsPaginado por número em vez de por cursor: items, total, page e pageSize. Peça a página seguinte com page:.
emails->sendBatchBatchResultNão é uma página: items, um para cada mensagem que enviou, com as contagens sent e failed.

Listas que devolvem o array da API

Algumas listas paginam por deslocamento, por número de página ou por um cursor numérico próprio, e devolvem o corpo descodificado tal como chegou, um array com data, em vez de uma Page. Não têm listAll nem iterate, por isso tem de as paginar você mesmo.

MétodoPagina comO que volta
exports->listlimit: e offset:data, total e hasMore.
imports->listFailuresafter: e limit:data, e nextCursor, um inteiro a devolver como after: que é null na última página.
subscriptions->list e subscriptions->listDomainslimit: e offset:data, total, counts e hasMore.
billing->listInvoicespage: e limit:data, total, page, limit, hasMore e 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'] !== []);

Uma lista que não é paginada, como languages->list, labels->listColors ou roles->listPermissions, devolve logo as suas linhas como uma lista simples.