تشغيل compat-legacy في الإنتاج
نظرة سريعة
قسم بعنوان «نظرة سريعة»المهايئ آمن للتشغيل في معالِجات HTTP، وعمّال الطوابير، والعمليات الطويلة الأمد. وهو أكثر أمانًا من TCPDF القديم 6.2.13 لأنه يزيل خطرَين إنتاجيين يُرجَّح أن تواجههما: الإخراج المباشر إلى المخزن المؤقت، واستدعاء die() عند حدوث خطأ. استعن بهذه الصفحة لتشغيله بالشكل الصحيح.
قبل الإنتاج، أكمِل تدقيق الوضع الصارم في /integrations/tcpdf-compat/migration/، وانشر مع تعطيل الوضع الصارم off.
معالجة المخرجات في العمّال والمعالِجات
قسم بعنوان «معالجة المخرجات في العمّال والمعالِجات»يكتب Output() في TCPDF القديم مباشرةً إلى المخزن المؤقت النشط للمخرجات. وقد يؤدي ذلك إلى إفساد الاستجابات في أُطر عمل HTTP وتعطيل عمّال الطوابير. بدلًا من ذلك، يوجّه المهايئ المخرجات عبر جسر وجهة آمن.
اختر الوجهة التي تناسب الجهة المُستدعِية:
| السياق | الوجهة | السبب |
|---|---|---|
| عامل طابور يكتب إلى وحدة التخزين | Output($path, 'F') | يكتب الملف ويُعيد سلسلة نصية فارغة، ولا يتفاعل مع المخزن المؤقت. |
| التوليد ثم attach/upload | Output($name, 'S') | يُعيد بايتات تنسيق المستندات المحمول (PDF)، وتتحكم أنت في وجهتها. |
| مرفق بريد إلكتروني | Output($name, 'E') | يُعيد متن امتدادات بريد الإنترنت متعددة الأغراض (MIME) بترميز base64 مع Content-Type: application/pdf. |
| استجابة HTTP تتحكم فيها | Output($name, 'S') | يحصل على البايتات، ثم تضبط الرؤوس والمتن بنفسك. |
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\Exception\TcpdfNotImplementedException;use NextPDF\Compat\Tcpdf\TCPDF;
/** * Render an invoice in a queue worker. Returns the storage path. * * @throws \RuntimeException on a render failure (Error() throws, not die()). */function renderInvoiceJob(array $invoice, string $storageDir): string{ $pdf = new TCPDF('P', 'mm', 'A4'); $pdf->SetFont('helvetica', '', 12); $pdf->AddPage(); $pdf->Cell(0, 10, 'Invoice ' . $invoice['number'], 0, 1);
$path = $storageDir . '/invoice-' . $invoice['number'] . '.pdf';
try { $pdf->Output($path, 'F'); // writes file, no buffer pollution } catch (TcpdfNotImplementedException $e) { // Only reachable if strict mode is on — it must NOT be in production. throw new \RuntimeException('Adapter strict-mode gap in production: ' . $e->getMessage(), 0, $e); } catch (\RuntimeException $e) { // Error() throws RuntimeException instead of die(). throw new \RuntimeException('PDF render failed: ' . $e->getMessage(), 0, $e); }
return $path;}في معالِج HTTP، فضّل 'S' واضبط الرؤوس بنفسك:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();$pdf->AddPage();$pdf->SetFont('helvetica', '', 12);$pdf->Cell(0, 10, 'Report');
$bytes = $pdf->Output('report.pdf', 'S');
header('Content-Type: application/pdf');header('Content-Length: ' . strlen($bytes));header('Content-Disposition: inline; filename="report.pdf"');echo $bytes;معالجة حالات الفشل
قسم بعنوان «معالجة حالات الفشل»يطلق Error() استثناء RuntimeException؛ ولا يستدعي die() أبدًا. هذا هو أهم تغيير تشغيلي مقارنةً بـ TCPDF القديم.
- غلِّف كل نقطة دخول للتصيير ضمن
try/catch. - اربط الاستثناء بعقد الأخطاء الخاص بتطبيقك، مثل HTTP 5xx، أو مهمة فاشلة، أو إعادة محاولة، أو رسالة معلّقة (dead-letter).
- لا تفترض أن العملية تنتهي عند فشل التصيير؛ فهي لا تنتهي.
إن ظهور TcpdfNotImplementedException في مهمة تكامل مستمر (CI) دورية بالوضع الصارم (موصى بها) يُعد نتيجة حقيقية. فهو يعني أن مسار شيفرة يعتمد على معامِل TCPDF غير مدعوم. تعامل معه بوصفه بند عمل في الترحيل، لا اختبارًا متقلبًا.
دورة الحياة وإدارة الموارد
قسم بعنوان «دورة الحياة وإدارة الموارد»- يبني المستند بايتات PDF الخاصة به على نحو كسول عند أول استدعاء للإخراج.
Close()اختياري؛ واستدعاؤه يخزّن البايتات مؤقتًا.Open()عملية لاغية آمنة. endPage()لا يفعل شيئًا لأن NextPDF يدير دورة حياة الصفحة. أزِله من الحلقات كثيفة التنفيذ؛ فهو لا يضيف أي قيمة.- دع PHP يجمع المهايئ ضمن عملية كنس المهملات بين المهام.
_destroy()يعيد ضبط البيانات المخزّنة مؤقتًا في المهايئ، لكنك لست بحاجة إلى استدعائه صراحةً في حلقات العمّال العادية. - أنشئ مهايئًا جديدًا لكل مستند. لا تُعِد استخدام نسخة مهايئ واحدة عبر مستندات غير مترابطة في عامل طويل الأمد؛ فحالة المستند خاصة بكل نسخة.
إرشادات الأداء
قسم بعنوان «إرشادات الأداء»- المهايئ طبقة تفويض رفيعة؛ والمحرك هو المهيمن على التكلفة، لا المهايئ.
- عرّف الثوابت القديمة مرة واحدة عند الإقلاع.
LegacyDefaults::register()وLegacyBootstrap::enableAliases()دالّتان مُتساويتا القوة ومحميّتان، لذلك تكون الاستدعاءات المتكررة قليلة الكلفة. تعريف الثوابت لكل طلب يهدر الجهد. - فضّل
Output(..., 'S')أو'F'على'I'/'D'في السياقات غير المتصفِّحة. يُنتج مسارا inline/download مخرجات مستقلة عن إطار العمل، وهي مخرجات لا ترغب فيها عادةً داخل عامل. - للتوليد بكميات كبيرة، حلِّل أداء المحرك، لا المهايئ. فميزانية الحِمل الإضافي الخاص بالمهايئ لكل صفحة صغيرة مقارنةً بالتصيير.
التزامن
قسم بعنوان «التزامن»- كل نسخة من المهايئ مستقلة وتحتفظ بحالة المستند الخاصة بها. التزامن على مستوى العملية أو العامل آمن عندما تستخدم كل وحدة عمل نسخة المهايئ الخاصة بها.
- تستخدم حواجز تساوي القوة في
LegacyBootstrapوLegacyDefaultsحالة ساكنة محلية للعملية؛ وهي آمنة ضمن نماذج PHP المعتادة per-request/per-worker. لكنها ليست مصممة لمشاركة حالة قابلة للتغيير عبر الخيوط.
قائمة تحقُّق ما قبل الإنتاج
قسم بعنوان «قائمة تحقُّق ما قبل الإنتاج»- اكتمل تدقيق الوضع الصارم، والإنتاج يعمل مع تعطيل الوضع الصارم.
- جميع نقاط دخول التصيير مُغلَّفة ضمن
try/catchمن أجلRuntimeException(دون الاعتماد علىdie()). - العمّال يستخدمون
Output(..., 'F')أو'S'، وليس مسار inline أبدًا. - الثوابت القديمة مُعرَّفة مرة واحدة عند الإقلاع، قبل أول إنشاء.
- توجد مهمة تكامل مستمر (CI) دورية بالوضع الصارم لالتقاط حالات التراجع.
- تأكيدات الاختبار على مستوى البايت أُعيد ضبط خطها الأساسي (راجع /integrations/tcpdf-compat/migration/).
انظر أيضًا
قسم بعنوان «انظر أيضًا»- /integrations/tcpdf-compat/security-and-operations/ — التشفير، ووضعية التوقيع، والتقوية
- /integrations/tcpdf-compat/troubleshooting/ — أنماط فشل الإنتاج وإصلاحاتها
- /integrations/tcpdf-compat/configuration/ — الوضع الصارم ونظافة الثوابت
- /integrations/tcpdf-compat/migration/ — التدقيق الذي يجب أن يسبق الإنتاج