الاستقرار: تجريبي
امتداد مخزَّن الصفحات المحتفَظ به
لمحة سريعة
قسم بعنوان «لمحة سريعة»امتداد اختياري، لا تكافؤ قديم. هذا الوسيط الإنشائي غير موجود في TCPDF 6.x القديم. وهو امتداد من NextPDF. وهو مُعطَّل افتراضيًا؛ ومع إيقافه، يتصرّف المحوِّل كما من قبل تمامًا، و
setPage()إلى صفحة سابقة يطرحUnsupportedFeatureExceptionكما طرح دائمًا.
يتيح لك TCPDF القديم استدعاء setPage() للانتقال إلى صفحة سابقة ومتابعة
الرسم. ولا يستطيع المحوِّل التدفّقي فعل ذلك افتراضيًا — فبمجرّد تفريغ صفحة
تختفي — فيطرح setPage() أو lastPage() إلى صفحة سابقة
UnsupportedFeatureException. ومخزَّن الصفحات المحتفَظ به هو الخيار الاختياري
الذي يُعيد سلوك إعادة الملء هذا فوق مخزَّن الصفحات المحتفَظ به في نواة
NextPDF.
تفعيل المخزَّن
قسم بعنوان «تفعيل المخزَّن»مرّر retainedPageBuffer: true إلى مُنشئ المحوِّل. ومع تفعيل المخزَّن، يُفوِّض
أي استدعاء setPage() أو lastPage() يستهدف صفحة سابقة إلى إعادة الملء في
النواة بدلًا من الطرح:
<?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');مثال إنتاجي: إعادة ملء صفحة غلاف محجوزة
قسم بعنوان «مثال إنتاجي: إعادة ملء صفحة غلاف محجوزة»سببٌ شائع للجوء إلى المخزَّن هو صفحة غلاف أو ملخّص لا تُعرَف
أرقامها إلا بعد تخطيط الجسم — إجمالي عدد الصفحات، أو مجموع
كلّي، أو عدد السجلّات. احجز الصفحة 1 مُقدَّمًا، وصيِّر الجسم، ثم
أعِد ملء الغلاف بـ setPage(1)، واستأنف في النهاية بـ lastPage().
يُبيّن هذا المثال أيضًا حدَّي الإغلاق الآمن اللذين يجب أن تعالجهما:
UnsupportedFeatureException للمحوِّل عند رقم صفحة خارج المدى، و
RetainedPageBufferIncompatibleException للنواة إذا فعّل المستند أيضًا
ميزةً غير متوافقة.
<?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(المحوِّل) — هدفsetPage()/lastPage()خارج المدى، أو أي تبديل لصفحة سابقة عندما يكون المخزَّن مُعطَّلًا.RetainedPageBufferIncompatibleException(النواة،NextPDF\Exception\Strict) — المخزَّن مُفعَّل لكنه مقترن بميزة لا يمكن إعادة اشتقاق بياناتها الوصفية على مستوى الصفحة بعد إعادة الملء. ولا يوجد نوعRetainedPageBufferInconsistency؛ فهذا هو استثناء عدم التوافق الوحيد، وأي خرق للميزانية يظهر كـ\OverflowException.
حدّ الإغلاق الآمن
قسم بعنوان «حدّ الإغلاق الآمن»يُفوِّض المحوِّل إلى مخزَّن الصفحات المحتفَظ به في النواة، فتنطبق الرفوضات نفسها. وتُرفَض إعادة الملء — بصرف النظر عن الترتيب وقبل التسلسل — عندما يستخدم المستند أيضًا أيًّا من:
- توقيع رقمي.
- PDF موسوم (شجرة بنية).
- PDF/A.
- الخطّية.
- حزم تدفّقات الكائنات.
- التعمية.
- وضع تصيير CSS الآمن.
كل رفض استثناء مُحدَّد النوع بإغلاق آمن — لا إسقاط صامت أبدًا:
- اقتران المخزَّن بأي ميزة أعلاه يطرح
RetainedPageBufferIncompatibleExceptionفي النواة (الفضاء الاسميNextPDF\Exception\Strict،@sinceنواة 6.1.0). والفحص مستقلّ عن الترتيب: يُطلَق سواء هُيّئت الميزة غير المتوافقة قبل الانضمام إلى المخزَّن أو بعده. - تحدّ ميزانية بايتات غير مضغوطة لكل مستند بمقدار 16 ميبيبايت المخزَّن؛
وتجاوزها يطرح
\OverflowExceptionوقت البناء بدلًا من إسقاط صفحة أُعيد ملؤها.
المقصد من الرفض أن إعادة الملء لا يمكنها أبدًا تغيير مستند موقَّع أو مُعمّى بصمت — فالاثنان لا يمكن تفعيلهما معًا.
ملاحظات سلوكية
قسم بعنوان «ملاحظات سلوكية»- مُعطَّل افتراضيًا. أنشِئ دون العَلَم ويكون المحوِّل دون تغيير؛
و
setPage()إلى صفحة سابقة لا يزال يطرحUnsupportedFeatureException. وهذا يُحافظ على عقد التدفّق لكل مُستدعٍ قائم. - لا تكافؤ قديم. لا يوجد في TCPDF القديم عَلَم مُنشئ
retainedPageBuffer. وثِّق هذا كامتداد من NextPDF عند الترحيل، حتى لا يُخطئ قارئ مستقبلي ويظنّه ميزة TCPDF. lastPage()يعود إلى النهاية. بعد إعادة الملء، استدعِlastPage()لـ استئناف الإلحاق عند الصفحة الأخيرة.- خطِّط لوضع واحد. إذا وجب توقيع المستند أو وسمه أو جعله PDF/A أو خطّيًا أو مُعمّى أو بتدفّق كائنات، فلا تُفعِّل المخزَّن؛ احسب مُقدَّمًا القيمة التي كنت ستُعيد ملؤها بدلًا من ذلك.