stabilità: Sperimentale
Estensione del buffer di pagina mantenuto
In sintesi
Sezione intitolata “In sintesi”Estensione opt-in, non parità legacy. Questo argomento del costruttore non esiste nel TCPDF 6.x legacy. È un’estensione NextPDF. È disattivato per impostazione predefinita; con esso spento, l’adattatore si comporta esattamente come prima, e
setPage()verso una pagina precedente sollevaUnsupportedFeatureExceptioncome ha sempre fatto.
Il TCPDF legacy ti consente di chiamare setPage() per tornare a una pagina
precedente e continuare a disegnare. L’adattatore in streaming non può farlo per
impostazione predefinita — una volta scaricata, una pagina è perduta — perciò
setPage() o lastPage() verso una pagina precedente solleva
UnsupportedFeatureException. Il buffer di pagina mantenuto è l’opt-in che
ripristina questo comportamento di ripopolamento sopra il buffer di pagina
mantenuto di NextPDF core.
Abilitare il buffer
Sezione intitolata “Abilitare il buffer”Passa retainedPageBuffer: true al costruttore dell’adattatore. Con il buffer
attivo, una chiamata setPage() o lastPage() che punta a una pagina precedente
delega al ripopolamento di core invece di sollevare un’eccezione:
<?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');Esempio di produzione: ripopolare una pagina di copertina riservata
Sezione intitolata “Esempio di produzione: ripopolare una pagina di copertina riservata”Un motivo comune per ricorrere al buffer è una pagina di copertina o di
riepilogo i cui numeri sono noti solo dopo che il corpo è stato disposto — un
conteggio totale delle pagine, un totale generale, un conteggio dei record.
Riserva la pagina 1 in anticipo, rendi il corpo, poi ripopola la copertina con
setPage(1) e riprendi alla fine con lastPage(). Questo esempio mostra anche i
due confini fail-closed che devi gestire: la UnsupportedFeatureException
dell’adattatore per un numero di pagina fuori intervallo, e la
RetainedPageBufferIncompatibleException di core se il documento abilita anche una
funzionalità incompatibile.
<?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, ); }}Distingui deliberatamente le due superfici di fallimento:
UnsupportedFeatureException(adattatore) — un targetsetPage()/lastPage()fuori intervallo, o qualsiasi passaggio a una pagina precedente quando il buffer è spento.RetainedPageBufferIncompatibleException(core,NextPDF\Exception\Strict) — il buffer è attivo ma combinato con una funzionalità i cui metadati a livello di pagina non possono essere riderivati dopo un ripopolamento. Non esiste alcun tipoRetainedPageBufferInconsistency; questa è l’unica eccezione di incompatibilità, e un superamento del budget emerge come\OverflowException.
Confine fail-closed
Sezione intitolata “Confine fail-closed”L’adattatore delega al buffer di pagina mantenuto di core, perciò si applicano gli stessi rifiuti. Il ripopolamento è rifiutato — indipendentemente dall’ordine e prima della serializzazione — quando il documento usa anche una qualsiasi di:
- Una firma digitale.
- PDF taggato (albero della struttura).
- PDF/A.
- Linearizzazione.
- Packing in object stream.
- Cifratura.
- Modalità di rendering CSS Safe.
Ogni rifiuto è un’eccezione tipizzata e fail-closed — mai uno scarto silenzioso:
- Combinare il buffer con una qualsiasi funzionalità sopra solleva la
RetainedPageBufferIncompatibleExceptiondi core (namespaceNextPDF\Exception\Strict,@sincecore 6.1.0). Il controllo è indipendente dall’ordine: scatta sia che la funzionalità incompatibile sia stata configurata prima sia dopo l’opt-in del buffer. - Un budget di byte non compressi di 16 MiB per documento limita il buffer;
superarlo solleva
\OverflowExceptional momento della build invece di scartare una pagina ripopolata.
Il senso del rifiuto è che un ripopolamento non può mai alterare silenziosamente un documento firmato o cifrato — i due non possono essere abilitati insieme.
Note comportamentali
Sezione intitolata “Note comportamentali”- Disattivato per impostazione predefinita. Costruisci senza il flag e
l’adattatore è invariato;
setPage()verso una pagina precedente solleva ancoraUnsupportedFeatureException. Questo preserva il contratto dello streaming per ogni chiamante esistente. - Non parità legacy. Il TCPDF legacy non ha alcun flag del costruttore
retainedPageBuffer. Documenta questo come un’estensione NextPDF quando migri, affinché un lettore futuro non lo scambi per una funzionalità TCPDF. lastPage()torna alla fine. Dopo un ripopolamento, chiamalastPage()per riprendere l’append all’ultima pagina.- Pianifica una sola modalità. Se il documento deve essere firmato, taggato, PDF/A, linearizzato, cifrato o con object stream, non abilitare il buffer; pre-calcola invece il valore che avresti ripopolato.