estabilidade: Experimental
PageBackfill: buffer de página retida
Visão geral
Seção intitulada “Visão geral”Pré-visualização opcional. O buffer de página retida é desativado por padrão. Com ele desativado, o escritor é o serializador em streaming que sempre foi — idêntico byte a byte. Ative-o somente quando você realmente precisar desenhar em uma página anterior, e leia primeiro a lista de falha fechada abaixo.
Por padrão, o escritor envia as páginas em streaming e as descarrega em ordem; uma vez que uma página é descarregada, não é mais possível desenhar nela. O buffer de página retida é o recurso opcional que mantém as páginas descarregadas para que uma página já descarregada possa ser preenchida posteriormente — desenhada em uma página anterior — antes de o documento ser serializado. O uso clássico é uma caixa de total ou de resumo que você só pode posicionar depois que as páginas posteriores tiverem sido dispostas.
Instalação
Seção intitulada “Instalação”composer require nextpdf/core:^3O buffer de página retida é entregue no pacote core.
Config::withRetainedPageBuffer() e os métodos de preenchimento posterior de
Document são @since 6.1.0. O padrão permanece o escritor em streaming. A
ADR-037, que anteriormente havia adiado essa capacidade, agora está registrada
como implementada.
Visão geral conceitual
Seção intitulada “Visão geral conceitual”Config::withRetainedPageBuffer() opta um documento por páginas retidas. Uma vez
ativado, Document::setActiveBackfillPage(int $pageIndex) redireciona o desenho
para uma página anterior, já descarregada; Document::endPageBackfill() retorna
o desenho à posição normal de anexação. O conteúdo que você escreve entre as duas
chamadas chega à página anterior. O buffer mantém as páginas até save(), então
o preenchimento posterior é aplicado antes de a tabela de referências cruzadas e
o trailer serem gravados (ISO 32000-2 §7.5).
Limite de falha fechada — combinações recusadas
Seção intitulada “Limite de falha fechada — combinações recusadas”O preenchimento posterior é uma operação de acesso aleatório, e vários recursos de documento pressupõem bytes em streaming, somente de anexação (append-only). O buffer de página retida se recusa a combinar com qualquer um deles, de forma independente da ordem e antes da serialização, para que nunca possa quebrar silenciosamente uma assinatura ou uma reivindicação de conformidade:
- Uma assinatura digital.
- PDF marcado (árvore de estrutura).
- PDF/A.
- Linearização.
- Empacotamento de object stream.
- Criptografia.
- Modo de renderização Safe CSS.
Um orçamento de bytes não comprimidos por documento limita quanto o buffer pode manter; um documento que o excede falha de forma rígida em vez de consumir memória sem limite. O padrão de streaming ainda falha fechado no momento em que um chamador tenta uma troca de acesso aleatório sem o recurso opcional — ativar o buffer é a única forma de obter o preenchimento posterior, e ele é incompatível com os recursos acima por construção.
Superfície da API
Seção intitulada “Superfície da API”| Símbolo | Localização | Função |
|---|---|---|
Config::withRetainedPageBuffer(bool $enabled = true): self | src/Core/Config.php | Opta um documento pelo buffer de página retida. |
Document::setActiveBackfillPage(int $pageIndex): static | src/Core/Document.php | Redireciona o desenho para uma página anterior, já descarregada. |
Document::endPageBackfill(): static | src/Core/Document.php | Retorna o desenho à posição normal de anexação. |
Uma tentativa de preenchimento posterior que viola uma combinação recusada levanta uma exceção de configuração tipada no limite, não um documento corrompido.
Exemplo de código — Início rápido
Seção intitulada “Exemplo de código — Início rápido”Reserve um espaço na página um, preencha o resto do documento e então preencha posteriormente o espaço reservado com um valor calculado no final.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;use NextPDF\Core\Document;
$config = (new Config())->withRetainedPageBuffer();
$doc = Document::createStandalone($config);$doc->addPage(); // page 0 — leaves room for a grand total$doc->writeHtml('<h1>Invoice</h1>');
$doc->addPage(); // page 1 — line items$doc->writeHtml('<p>Line items…</p>');$total = 1234.56; // computed after laying out the items
$doc->setActiveBackfillPage(0); // draw back onto page 0$doc->writeHtml('<p>Grand total: ' . number_format($total, 2) . '</p>');$doc->endPageBackfill();
$doc->save(__DIR__ . '/invoice.pdf');Exemplo de código — Produção
Seção intitulada “Exemplo de código — Produção”Mantenha o buffer desativado para qualquer documento assinado, marcado, PDF/A, linearizado, criptografado ou com object stream — essas são exatamente as combinações que o buffer recusa. Escolha um caminho explicitamente.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;use NextPDF\Core\Document;
function renderReport(bool $needsBackfill, bool $mustBeSigned): Document{ if ($needsBackfill && $mustBeSigned) { // The buffer refuses to combine with signing. Resolve the requirement // before building: pre-compute the value, or sign a separate pass. throw new \LogicException('Back-fill and signing are mutually exclusive.'); }
$config = new Config(); if ($needsBackfill) { $config = $config->withRetainedPageBuffer(); }
return Document::createStandalone($config);}Casos extremos e pegadinhas
Seção intitulada “Casos extremos e pegadinhas”- Desativado é idêntico byte a byte. Com o buffer desativado, o escritor faz streaming como antes.
- Mutuamente exclusivo com assinatura, marcação (tagging), PDF/A, linearização, object streams, criptografia e o modo Safe CSS. A recusa é independente da ordem e dispara antes da serialização. Planeje o documento para um modo ou o outro.
- Um orçamento de bytes falha de forma rígida. O buffer retido é limitado; um documento que excede o orçamento de bytes não comprimidos falha em vez de crescer sem limite.
- Emparelhe as chamadas. Cada
setActiveBackfillPage()deve ser correspondido por umendPageBackfill()para que o conteúdo posterior seja anexado normalmente. - O padrão de streaming recusa acesso aleatório. Sem o recurso opcional, uma troca de acesso aleatório falha fechada. O buffer é o único caminho suportado.
Desempenho
Seção intitulada “Desempenho”O buffer de página retida troca memória pela capacidade de preenchimento
posterior: ele mantém as páginas descarregadas até save(), limitado pelo
orçamento de bytes não comprimidos por documento. O perfil de memória plano do
escritor em streaming se aplica apenas com o buffer desativado. O
performance_budget (wall_ms: 1500, peak_mb: 128) reflete o teto de memória
mais alto do caminho retido.
Notas de segurança
Seção intitulada “Notas de segurança”O buffer de página retida não amplia a superfície de entrada; ele altera quando os bytes são serializados, não o que é ingerido. Sua recusa em combinar com criptografia e assinatura é uma propriedade de segurança: um preenchimento posterior nunca pode alterar bytes assinados ou criptografados após o fato, porque os dois não podem ser ativados juntos. O orçamento de bytes limita a memória contra um documento hostil.
Conformidade
Seção intitulada “Conformidade”| Declaração | Especificação | Cláusula |
|---|---|---|
| O escritor serializa o corpo, a estrutura de referências cruzadas e o trailer no momento do salvamento. | ISO 32000-2 | §7.5 |
Esta é uma capacidade de pré-visualização. O NextPDF recusa o buffer de preenchimento posterior para documentos assinados, marcados, PDF/A, linearizados, criptografados e com object stream, de modo que não faz nenhuma reivindicação de conformidade para esses perfis por este caminho. Nenhum texto de norma é reproduzido.
Adaptador de compatibilidade (TCPDF)
Seção intitulada “Adaptador de compatibilidade (TCPDF)”O adaptador de compatibilidade TCPDF expõe essa capacidade como uma extensão de
construtor. Construa o adaptador com retainedPageBuffer: true, e então uma
chamada setPage() ou lastPage() que aponte para uma página anterior delega ao
preenchimento posterior do core em vez de levantar a UnsupportedFeatureException
de streaming. Este argumento de construtor é uma extensão do NextPDF, não
paridade com o TCPDF legado — o TCPDF legado não tem tal flag. As mesmas
recusas de falha fechada se aplicam. Consulte a página do buffer de página retida
do adaptador de compatibilidade para os detalhes do lado do adaptador.