ความเสถียร: ทดลอง
ส่วนขยาย Retained page buffer
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”ส่วนขยายแบบ opt-in ไม่ใช่ความเท่าเทียมกับของดั้งเดิม อาร์กิวเมนต์ตัวสร้างนี้ ไม่มีอยู่ใน TCPDF 6.x ดั้งเดิม มันเป็นส่วนขยายของ NextPDF มันเปิดเป็นค่าเริ่มต้นปิด; เมื่อมันปิด adapter ทำงานเหมือนเดิมทุกประการ และ
setPage()ไปยังหน้าก่อนหน้า จะยกUnsupportedFeatureExceptionอย่างที่มันเป็นมาตลอด
TCPDF ดั้งเดิมให้คุณเรียก setPage() เพื่อย้อนกลับไปยังหน้าก่อนหน้าและวาดต่อ
streaming adapter ทำเช่นนั้นไม่ได้โดยค่าเริ่มต้น — เมื่อหน้าถูก flush แล้ว มันก็หายไป —
ดังนั้น setPage() หรือ lastPage() ไปยังหน้าก่อนหน้าจะยก UnsupportedFeatureException
retained page buffer คือ opt-in ที่คืนพฤติกรรม back-fill นี้บน retained page buffer
ของ NextPDF core
เปิดใช้บัฟเฟอร์
หัวข้อที่มีชื่อว่า “เปิดใช้บัฟเฟอร์”ส่ง retainedPageBuffer: true ไปยังตัวสร้างของ adapter เมื่อบัฟเฟอร์เปิด การเรียก
setPage() หรือ lastPage() ที่เล็งไปยังหน้าก่อนหน้าจะมอบหมายให้ core back-fill แทน
ที่จะยก:
<?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');ตัวอย่างการใช้งานจริง: back-fill หน้าปกที่จองไว้
หัวข้อที่มีชื่อว่า “ตัวอย่างการใช้งานจริง: back-fill หน้าปกที่จองไว้”เหตุผลทั่วไปในการใช้บัฟเฟอร์คือ หน้าปกหรือหน้าสรุปที่ตัวเลขรู้ได้หลังจากจัดเนื้อหา
แล้วเท่านั้น — จำนวนหน้าทั้งหมด ยอดรวม จำนวนระเบียน จองหน้า 1 ไว้ล่วงหน้า เรนเดอร์
เนื้อหา จากนั้น back-fill หน้าปกด้วย setPage(1) และกลับมาทำงานต่อตอนท้ายด้วย
lastPage() ตัวอย่างนี้ยังแสดงขอบเขต fail-closed สองอย่างที่คุณต้องจัดการ:
UnsupportedFeatureException ของ adapter สำหรับหมายเลขหน้าที่อยู่นอกช่วง และ
RetainedPageBufferIncompatibleException ของ core หากเอกสารยังเปิดใช้คุณสมบัติ
ที่เข้ากันไม่ได้ด้วย
<?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, ); }}แยกแยะพื้นผิวความล้มเหลวสองอย่างอย่างจงใจ:
UnsupportedFeatureException(adapter) — เป้าหมายsetPage()/lastPage()ที่ อยู่นอกช่วง หรือ การสลับไปหน้าก่อนหน้าใด ๆ เมื่อบัฟเฟอร์ ปิดRetainedPageBufferIncompatibleException(core,NextPDF\Exception\Strict) — บัฟเฟอร์ เปิด แต่ถูกรวมกับคุณสมบัติที่เมตาดาทาระดับหน้าไม่สามารถ re-derive ได้หลัง back-fill ไม่มีชนิดRetainedPageBufferInconsistency; นี่คือ ข้อยกเว้นความไม่เข้ากันเดียว และการเกินงบประมาณปรากฏเป็น\OverflowException
ขอบเขต fail-closed
หัวข้อที่มีชื่อว่า “ขอบเขต fail-closed”adapter มอบหมายให้ core retained page buffer ดังนั้นการปฏิเสธเดียวกันจึงใช้บังคับ back-fill ถูกปฏิเสธ — โดยไม่ขึ้นกับลำดับและก่อน serialization — เมื่อเอกสารยังใช้สิ่ง ใดสิ่งหนึ่งในนี้ด้วย:
- ลายเซ็นดิจิทัล
- Tagged PDF (structure tree)
- PDF/A
- Linearization
- การแพ็ค object stream
- การเข้ารหัส
- โหมดการเรนเดอร์ CSS แบบ Safe
การปฏิเสธแต่ละอย่างเป็นข้อยกเว้นแบบมีชนิดและ fail-closed — ไม่ใช่การตัดทิ้งที่เงียบ ๆ:
- การรวมบัฟเฟอร์กับคุณสมบัติใด ๆ ข้างต้นจะยก core
RetainedPageBufferIncompatibleException(เนมสเปซNextPDF\Exception\Strict,@sincecore 6.1.0) การตรวจสอบไม่ขึ้นกับลำดับ: มันทำงานไม่ว่าคุณสมบัติที่เข้ากัน ไม่ได้จะถูกกำหนดค่าก่อนหรือหลัง opt-in บัฟเฟอร์ - งบประมาณไบต์ที่ไม่บีบอัด 16 MiB ต่อเอกสารกำหนดขอบเขตบัฟเฟอร์; การเกินมัน
จะยก
\OverflowExceptionในเวลา build แทนที่จะตัดทิ้งหน้าที่ back-fill แล้ว
ประเด็นของการปฏิเสธคือ back-fill ไม่มีทางเปลี่ยนแปลงเอกสารที่ลงนามหรือเข้ารหัส อย่างเงียบ ๆ — สองสิ่งนี้เปิดพร้อมกันไม่ได้
หมายเหตุด้านพฤติกรรม
หัวข้อที่มีชื่อว่า “หมายเหตุด้านพฤติกรรม”- เปิดเป็นค่าเริ่มต้นปิด สร้างโดยไม่มีแฟล็กแล้ว adapter ไม่เปลี่ยนแปลง;
setPage()ไปยังหน้าก่อนหน้ายังยกUnsupportedFeatureExceptionสิ่งนี้รักษา สัญญา streaming สำหรับผู้เรียกใช้ที่มีอยู่ทุกราย - ไม่ใช่ความเท่าเทียมกับของดั้งเดิม TCPDF ดั้งเดิมไม่มีแฟล็กตัวสร้าง
retainedPageBufferบันทึกสิ่งนี้เป็นส่วนขยายของ NextPDF เมื่อคุณ migrate เพื่อไม่ให้ผู้อ่านในอนาคตเข้าใจผิดว่ามันเป็นคุณสมบัติของ TCPDF lastPage()กลับไปยังท้าย หลัง back-fill ให้เรียกlastPage()เพื่อทำงานต่อ ในการต่อท้ายที่หน้าสุดท้าย- วางแผนหนึ่งโหมด หากเอกสารต้องลงนาม tagged, PDF/A, linearized, เข้ารหัส หรือ object-stream อย่าเปิดบัฟเฟอร์; คำนวณค่าที่คุณจะ back-fill ล่วงหน้าแทน