estabilidade: Experimental
Extensão de buffer de página retida
Visão geral
Seção intitulada “Visão geral”Extensão opcional, não paridade legada. Este argumento de construtor não existe no TCPDF 6.x legado. É uma extensão NextPDF. É desativada por padrão; com ela desativada, o adaptador se comporta exatamente como antes, e
setPage()para uma página anterior levantaUnsupportedFeatureExceptioncomo sempre.
O TCPDF legado permite que você chame setPage() para voltar a uma página
anterior e continuar desenhando. O adaptador de streaming não consegue fazer isso
por padrão — uma vez que uma página é descarregada, ela se foi — então setPage()
ou lastPage() para uma página anterior levanta UnsupportedFeatureException. O
buffer de página retida é o recurso opcional que restaura esse comportamento de
preenchimento posterior sobre o buffer de página retida do core do NextPDF.
Ativar o buffer
Seção intitulada “Ativar o buffer”Passe retainedPageBuffer: true para o construtor do adaptador. Com o buffer
ativado, uma chamada setPage() ou lastPage() que aponte para uma página
anterior delega ao preenchimento posterior do core em vez de levantar a exceção:
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF(retainedPageBuffer: true);
$pdf->AddPage(); // page 1 — reserve room for a running total$pdf->Cell(0, 10, 'Invoice', ln: 1);
$pdf->AddPage(); // page 2 — line items$pdf->Cell(0, 10, 'Line items…', ln: 1);$total = 1234.56; // known only after the items are laid out
$pdf->setPage(1); // delegates to the core back-fill$pdf->Cell(0, 10, 'Grand total: ' . number_format($total, 2), ln: 1);$pdf->lastPage(); // return to the final page
$pdf->Output(__DIR__ . '/invoice.pdf', 'F');Exemplo de produção: preencher posteriormente uma página de capa reservada
Seção intitulada “Exemplo de produção: preencher posteriormente uma página de capa reservada”Um motivo comum para recorrer ao buffer é uma página de capa ou de resumo cujos
números só são conhecidos depois que o corpo é disposto — uma contagem total de
páginas, um total geral, uma contagem de registros. Reserve a página 1 de
antemão, renderize o corpo e então preencha posteriormente a capa com
setPage(1), e retome no final com lastPage(). Este exemplo também mostra os
dois limites de falha fechada que você deve tratar: a UnsupportedFeatureException
do adaptador para um número de página fora do intervalo e a
RetainedPageBufferIncompatibleException do core se o documento também ativar um
recurso incompatível.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\Exception\UnsupportedFeatureException;use NextPDF\Compat\Tcpdf\TCPDF;use NextPDF\Exception\Strict\RetainedPageBufferIncompatibleException;
/** * Render a multi-page report whose cover page summarises figures that are * only known once every body page has been laid out. * * @param list<array{label: string, amount: float}> $lineItems */function renderReport(array $lineItems, string $destination): void{ // Opt in to the back-fill buffer. Default-off; this is a NextPDF // extension, not legacy TCPDF parity. (Underlying core feature: 6.1.0.) $pdf = new TCPDF(retainedPageBuffer: true);
// Page 1 — the cover. Reserve it now; the summary is filled in last. $pdf->AddPage(); $pdf->Cell(0, 10, 'Quarterly report', ln: 1);
// Body pages — lay out the line items, accumulating the running total. $pdf->AddPage(); $total = 0.0; foreach ($lineItems as $item) { $total += $item['amount']; $pdf->Cell(0, 8, $item['label'] . ': ' . number_format($item['amount'], 2), ln: 1); }
// Back-fill the cover with figures known only now. setPage() delegates to // the core back-fill in retained mode; an out-of-range page number still // fails closed with UnsupportedFeatureException in BOTH modes. try { $pdf->setPage(1); } catch (UnsupportedFeatureException $e) { throw new RuntimeException('Cover page was not reserved: ' . $e->getMessage(), previous: $e); } $pdf->Cell(0, 10, 'Total: ' . number_format($total, 2), ln: 1); $pdf->Cell(0, 10, 'Line items: ' . count($lineItems), ln: 1);
// Resume appending at the final page before output. $pdf->lastPage();
// Output() drives the core build. If the document had also enabled a // back-fill-incompatible feature (signing, tagging, PDF/A, linearization, // object streams, encryption, Safe CSS mode), the core refuses here, // order-independently, with RetainedPageBufferIncompatibleException — the // back-fill can never silently corrupt such a document. try { $pdf->Output($destination, 'F'); } catch (RetainedPageBufferIncompatibleException $e) { // $e->feature names the incompatible feature, e.g. 'signature'. throw new RuntimeException( 'Back-fill is incompatible with ' . $e->feature . '; render pages in order instead.', previous: $e, ); }}Distinga as duas superfícies de falha deliberadamente:
UnsupportedFeatureException(adaptador) — um alvo desetPage()/lastPage()fora do intervalo, ou qualquer troca para página anterior quando o buffer está desativado.RetainedPageBufferIncompatibleException(core,NextPDF\Exception\Strict) — o buffer está ativado, mas combinado com um recurso cujos metadados de nível de página não podem ser rederivados após um preenchimento posterior. Não existe um tipoRetainedPageBufferInconsistency; esta é a única exceção de incompatibilidade, e uma violação de orçamento aparece como\OverflowException.
Limite de falha fechada
Seção intitulada “Limite de falha fechada”O adaptador delega ao buffer de página retida do core, então as mesmas recusas se aplicam. O preenchimento posterior é recusado — de forma independente da ordem e antes da serialização — quando o documento também usa qualquer um de:
- Uma assinatura digital.
- PDF marcado (árvore de estrutura).
- PDF/A.
- Linearização.
- Empacotamento de object stream.
- Criptografia.
- Modo de renderização Safe CSS.
Cada recusa é uma exceção tipada de falha fechada — nunca um descarte silencioso:
- Combinar o buffer com qualquer recurso acima levanta a
RetainedPageBufferIncompatibleExceptiondo core (namespaceNextPDF\Exception\Strict,@sincecore 6.1.0). A verificação é independente da ordem: ela dispara independentemente de o recurso incompatível ter sido configurado antes ou depois de o buffer ser ativado. - Um orçamento de bytes não comprimidos de 16 MiB por documento limita o
buffer; excedê-lo levanta
\OverflowExceptionno momento da build em vez de descartar uma página preenchida posteriormente.
O ponto da recusa é que um preenchimento posterior nunca pode alterar silenciosamente um documento assinado ou criptografado — os dois não podem ser ativados juntos.
Notas comportamentais
Seção intitulada “Notas comportamentais”- Desativado por padrão. Construa sem a flag e o adaptador permanece
inalterado;
setPage()para uma página anterior ainda levantaUnsupportedFeatureException. Isso preserva o contrato de streaming para todo chamador existente. - Não é paridade legada. O TCPDF legado não tem a flag de construtor
retainedPageBuffer. Documente isso como uma extensão NextPDF quando migrar, para que um leitor futuro não a confunda com um recurso do TCPDF. lastPage()retorna ao final. Após um preenchimento posterior, chamelastPage()para retomar a anexação na página final.- Planeje um modo. Se o documento precisar ser assinado, marcado, PDF/A, linearizado, criptografado ou empacotado em object stream, não ative o buffer; em vez disso, pré-calcule o valor que você teria preenchido posteriormente.