ترحيل قاعدة شيفرة TCPDF 6.x إلى NextPDF
لمحة سريعة
قسم بعنوان «لمحة سريعة»توفّر حزمة nextpdf/compat-legacy أسماء الطرائق العامة في TCPDF 6.x وترتيب معاملاتها وقيمها الافتراضية فوق محرك نواة NextPDF عبر المحوّل NextPDF\Compat\Tcpdf\TCPDF. رحّل بهذا الترتيب: انتقل إلى المحرك بأصغر تغيير ممكن، وثبّت ما يعمل بالفعل، وفعّل الوضع الصارم لاكتشاف ما لا يعمل، وأصلح مواضع الاستدعاء واحدًا تلو الآخر، ثم أوقف المحوّل واستخدم الواجهة البرمجية الحديثة. يدعم المحوّل عملية الترحيل؛ وهو ليس الوجهة النهائية.
ابدأ بالمتطلبات المسبقة:
- نواة NextPDF و
nextpdf/compat-legacyمثبَّتتان. - لديك قاعدة شيفرة TCPDF 6.x قائمة ومزوّدة بمجموعة اختبارات. تمثّل مجموعة الاختبارات شبكة الأمان لكل مرحلة من المراحل أدناه.
هذا دليل إجرائي. للاطلاع على سلوك كل طريقة من طرائق TCPDF، اقرأ صفحة تغطية الطرائق. وللاطلاع على الاستراتيجية الكاملة ملفًا بملف مع الشيفرة، اقرأ صفحة الترحيل في المستودع الأصلي. ستجد الرابطين كليهما ضمن قسم اطّلع أيضًا.
التثبيت
قسم بعنوان «التثبيت»ثبّت المحوّل إلى جانب النواة. لا تُزِل مكتبة TCPDF الحقيقية بعد — فالاحتفاظ بكلتيهما يتيح لك مقارنة الناتج أثناء الترحيل.
composer require nextpdf/compat-legacyقبل أن تغيّر أي شيفرة، تأكّد من أن قيد المحرك قابل للحل (nextpdf/core ^3.0) وأن مجموعة الاختبارات لا تزال تعمل.
نظرة مفاهيمية
قسم بعنوان «نظرة مفاهيمية»المحوّل طبقة توافق، وليس تفريعًا من TCPDF ولا نسخة مطابقة بايتًا ببايت. من بين نحو 120 طريقة عامة شملها المسح في TCPDF 6.x، ترتبط نحو 94 طريقة مباشرةً بعملية في NextPDF\Core\Document وتعمل على نحو متوافق مع المعاملات الموثّقة. أما أقلية محدّدة فإما تقبل معاملات قديمة لا يراعيها المحرك (تجاهل صامت)، أو لا تنتج أي ناتج (غير مُنفَّذة أو غير منطبقة). توجد مصفوفة التغطية المرجعية المتحقَّق منها بالاختبارات في مستودع الحزمة عند docs/TCPDF_COVERAGE.md. وعند تعارض هذا الدليل مع تلك المصفوفة، فالمرجع هو المصفوفة.
تحكم حقيقتان عملية الترحيل بأكملها:
- تختلف بايتات الناتج. المحرك تنفيذ مستقل لـ PDF 2.0، لذا تختلف بايتات الإخراج عن ناتج TCPDF حتى عندما تبدو النتيجة المرئية متطابقة. تحتاج الاختبارات التي تتحقّق من بايتات PDF بالضبط إلى إعادة ضبط مراجعها على المحتوى المعروض أو على الخصائص البنيوية.
- الوضع الصارم هو أداة التدقيق لديك. عند إيقاف الوضع الصارم (الإعداد الافتراضي)، تتراجع الطرائق التي لا يمكنها إعادة إنتاج سلوك TCPDF بصمت. وعند تفعيل الوضع الصارم، تطرح تلك الاستدعاءات
TcpdfNotImplementedException، مع تسمية المعاملات المتجاهَلة بدقة وتقديم تلميح للترحيل. شغّل الوضع الصارم في تمريرة تدقيق مخصّصة، ولا تشغّله أبدًا في الإنتاج.
يوفّر المحوّل أيضًا مستند المحرك المُغلَّف عبر getDocument()، الذي يعيد NextPDF\Core\Document. استخدم ذلك بوصفه مسار الخروج: رحّل مواضع الاستدعاء إلى الواجهة البرمجية الحديثة واحدًا تلو الآخر حتى تتمكّن من إزالة المحوّل.
سطح الواجهة البرمجية
قسم بعنوان «سطح الواجهة البرمجية»| الموضوع | السطح |
|---|---|
| الإنشاء | new NextPDF\Compat\Tcpdf\TCPDF('P', 'mm', 'A4') |
| أسماء عامة بديلة اختيارية | NextPDF\Compat\Tcpdf\LegacyBootstrap::enableAliases() |
| تفعيل التدقيق | TCPDF::setStrictMode(true) |
| استثناء التدقيق | NextPDF\Compat\Tcpdf\Exception\TcpdfNotImplementedException |
| مخرج طوارئ نحو الواجهة البرمجية الحديثة | TCPDF::getDocument(): NextPDF\Core\Document |
| الإخراج | TCPDF::Output(string $name, string $dest) — S، F، E، I، D |
LegacyBootstrap::enableAliases() غير حسّاس للتكرار (idempotent). فهو يسجّل \TCPDF و\TCPDF_STATIC و\TCPDF_FONTS و\TCPDF_COLORS و\TCPDF_IMAGES فقط عندما لا تكون تلك الأصناف موجودة أصلًا. توضّح صفحتا تغطية الطرائق والبدء السريع المرتبطتان ضمن قسم اطّلع أيضًا السلوك الكامل لكل طريقة ووجهات الإخراج.
مثال شيفرة — البدء السريع
قسم بعنوان «مثال شيفرة — البدء السريع»غيّر سطر الاستيراد، واحتفظ باستدعاءات نمط TCPDF، وأنتج ملف PDF.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF('P', 'mm', 'A4');$pdf->SetCreator('Quickstart');$pdf->SetTitle('First Document');$pdf->SetFont('helvetica', '', 12);$pdf->AddPage();$pdf->Cell(0, 10, 'Hello from the NextPDF engine', 1, 1, 'C');
$pdf->Output(__DIR__ . '/quickstart.pdf', 'F');Output($name, 'F') يكتب الملف ويعيد سلسلة فارغة. وعلى خلاف TCPDF القديم، لا تكتب Output() الخاصة بالمحوّل إلى مخزن الإخراج النشط، لذا يمكنك استدعاؤها بأمان داخل عامل طابور أو معالِج HTTP يتحكّم في استجابته الخاصة.
عندما يتعذّر عليك تغيير مواضع الاستدعاء التي تنشئ new \TCPDF(...) في النطاق العام، فعّل الأسماء البديلة الاختيارية مرة واحدة عند الإقلاع.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\LegacyBootstrap;
LegacyBootstrap::enableAliases();
// Legacy code now resolves \TCPDF to the adapter:$pdf = new \TCPDF('P', 'mm', 'A4');$pdf->AddPage();$pdf->SetFont('helvetica', '', 12);$pdf->Cell(0, 10, 'Legacy call site, modern engine');$pdf->Output(__DIR__ . '/aliased.pdf', 'F');لا تفعّل الأسماء البديلة بينما مكتبة TCPDF الحقيقية لا تزال قابلة للتحميل التلقائي. يُتخطّى الاسم البديل عندما يكون الصنف \TCPDF موجودًا أصلًا، لذا قد تستمر في استخدام TCPDF القديم دون أن تدري. أثناء الترحيل، فضّل عمليات الاستيراد لكل ملف على حدة.
مثال شيفرة — الإنتاج
قسم بعنوان «مثال شيفرة — الإنتاج»الخطوة الآمنة للترحيل هي تدقيق الوضع الصارم. شغّل مسارًا تمثيليًا من الإنتاج، أو مجموعة الاختبارات، مع تفعيل الوضع الصارم، واجمع كل TcpdfNotImplementedException. كل استثناء هو بند عمل: فهو يسمّي الطريقة، ويحدّد المعاملات المتجاهَلة، ويقدّم تلميحًا.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\Exception\TcpdfNotImplementedException;use NextPDF\Compat\Tcpdf\TCPDF;
function renderInvoice(TCPDF $pdf): void{ // ... your existing rendering code, unchanged ...}
$pdf = new TCPDF('P', 'mm', 'A4');$pdf->setStrictMode(true);
try { renderInvoice($pdf); $pdf->Output(__DIR__ . '/audit.pdf', 'F');} catch (TcpdfNotImplementedException $exception) { // Each message names the method, the ignored parameters, and a hint. fwrite(STDERR, 'MIGRATION GAP: ' . $exception->getMessage() . "\n");}لكل فجوة، اختر أقل إصلاح صحيح كلفةً: أسقِط معاملًا لم تعتمد عليه قط، أو عبّر عن المقصد عبر الواجهة البرمجية الحديثة باستخدام getDocument(). يتولّى مخرج الطوارئ كل ما يعجز سطح TCPDF عن التعبير عنه.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();$pdf->AddPage();
// Legacy path stays for the parts that already work:$pdf->SetFont('helvetica', '', 12);$pdf->Cell(0, 10, 'Header line', 0, 1);
// Modern path for what the TCPDF surface cannot express here —// for example a clickable image (the legacy Image() link parameter// is one of the silently ignored parameters):$document = $pdf->getDocument();$document->image('logo.png', 10, 30, 40, 0);$document->link(10, 30, 40, 20, 'https://example.com');شغّل الوضع الصارم بوصفه مهمة تكامل مستمر (CI) مخصّصة، ثم أوقفه وانشر مسار الشيفرة المُدقَّق. احتفظ بمهمة تكامل مستمر دورية تعمل بالوضع الصارم لالتقاط الانحدارات أثناء إعادة الهيكلة.
الحالات الحدّية والمزالق
قسم بعنوان «الحالات الحدّية والمزالق»- تعيد
MultiCell()القيمة1، وتعيدWrite()القيمة0. هذه قيم موضوعة للتوافق، وليست قيمًا محسوبة. عدّل أي شيفرة تتفرّع بناءً على تلك القيم المُعادة. - تطرح
Error()استثناءً بدلًا من استدعاءdie(). يطرح المحوّلRuntimeException. يجب أن تلتقط الشيفرة التي تعتمد على إنهاء العملية هذا الاستثناء. - المعاملات ذات التجاهل الصامت. تقبل طرائق مثل
Image()وwriteHTML()وSetProtection()وBookmark()معاملات قديمة يجري تجاهلها. استخدم الوضع الصارم للعثور عليها. لإنشاء صورة قابلة للنقر، ارسم الصورة، ثم أضفDocument::link()فوق المستطيل نفسه. - الطرائق غير المُنفَّذة.
setSignature()وaddEmptySignatureAppearance()وendPage()هي عمليات لا أثر لها وتطرح استثناءً في الوضع الصارم؛ أماOpen()فهي عملية آمنة لا أثر لها ولا تطرح استثناءً أبدًا. أزِلendPage()وOpen(). يتطلّب التوقيع إصدارًا تجاريًا من NextPDF عبر الواجهة البرمجية الحديثة للتوقيع. - إصدار PDF ثابت. لا يمكن لـ
setPDFVersion()أن تستهدف إصدار PDF أقدم؛ فالناتج دائمًا PDF 2.0.setUserRights()مهملة في PDF 2.0 ويجري تجاهلها مع إصدار إشعار. - تعارض الأسماء البديلة. إذا ظل أي شيء يُحلّ إلى صنف TCPDF الحقيقي بعد إزالتك
tecnickcom/tcpdf، فإن التحذير الخاص بالأسماء البديلة ينطبق — استورد المحوّل صراحةً في مواضع الاستدعاء تلك.
الأداء
قسم بعنوان «الأداء»يفوّض المحوّل العمل إلى المحرك؛ وتتناسب كلفة بناء المستند مع المحتوى، لا مع طبقة المحوّل. ولأن Output() الخاصة بالمحوّل لا تكتب إلى مخزن الإخراج، فهي آمنة داخل عامل طابور — انقل التوليد الثقيل بأسلوب TCPDF بعيدًا عن خيط الطلب بالطريقة نفسها التي تنقل بها أي توليد في NextPDF. تُعدّ إعادة ضبط مراجع الاختبارات من مستوى البايت إلى المحتوى المعروض كلفة لمرة واحدة، وهي تمنحك اختبارات تصمد أمام ترقيات المحرك المستقبلية.
ملاحظات الأمان
قسم بعنوان «ملاحظات الأمان»- التشفير. تتجاهل
SetProtection()المعاملين القديمينmodeوpubkeys؛ ويستخدم المحرك AES-256 للمعالِج القياسي. للتشفير المعتمد على الشهادات، استخدم نقطة دخول التشفير بالمفتاح العام الحديثة التي يوفّرها المحوّل، لا المعاملات القديمة. - التوقيع مقيَّد. دعم التوقيع الأساسي قدرة خاصة بالإصدار التجاري يجري الوصول إليها عبر الواجهة البرمجية الحديثة للتوقيع باستخدام كائن قيمة شهادة؛ أما
setSignature()القديمة فهي عملية لا أثر لها. لا يقدّم هذا الدليل أي ادعاء بشأن ملفات تعريف التوقيع ذات التحقق طويل الأمد أو الموسومة زمنيًا لأي إصدار. - اجعل الإخفاق صريحًا أثناء التدقيق. يجعل الوضع الصارم الفقد الصامت للمعاملات مرئيًا، فتعرف متى لم يلتزم المحوّل بمقصد المستدعي. تعامل مع الاستثناءات المجمّعة بوصفها قائمة عمل الترحيل، لا بوصفها سلوك الإنتاج.
- لا تكتب أبدًا كتلة
catchفارغة. يلتقط مثال التدقيقTcpdfNotImplementedExceptionويكتب سطر بند عمل محدَّد.
تجد تفاصيل التشفير والتوقيع الكاملة أثناء الترحيل في صفحة الأمان والتشغيل الخاصة بـ compat-legacy.
المطابقة
قسم بعنوان «المطابقة»لا يقدّم هذا الدليل أي ادعاء معياري خاص به. يكتب المحوّل ناتج PDF 2.0 (ISO 32000-2) ولا يمكنه استهداف إصدار أقدم. هذا السلوك وهذا القيد موثّقان في صفحة تغطية الطرائق في المستودع الأصلي، التي تسجّل أيضًا مبدأ OWASP في الإخفاق الصريح وراء الوضع الصارم وإطار اكتمال الوظائف وفق ISO/IEC 25023 لتدقيق التغطية. تعيد هذه الصفحة العملية عرض الاستخدام وتحيل تلك الاستشهادات إلى صفحة المستودع الأصلي.
اطّلع أيضًا
قسم بعنوان «اطّلع أيضًا»- إرجاع ملف PDF مُولَّد من وحدة تحكّم — أعِد ناتج المحوّل بوصفه استجابة HTTP.
- البدء السريع لـ compat-legacy — المستند الأول، ووجهات الإخراج، ومخرج الطوارئ.
- تغطية طرائق TCPDF — تدقيق كل طريقة والمصفوفة المرجعية.
- الترحيل من TCPDF 6.x إلى NextPDF — الاستراتيجية الكاملة المؤلّفة من ست مراحل مع الشيفرة.