محرّك واحد، لكل إطار عمل
Spec: PSR-11 Container, §1.1.2PSR-11 Container §1.1.2Spec: PSR-4 Autoloader, §3PSR-4 Autoloader §3
لمحة سريعة
قسم بعنوان «لمحة سريعة»تنتهي أغلب منظومات PHP النامية بأكثر من إطار عمل واحد. وNextPDF محرّك PDF واحد يلتقي بكلٍّ منها بشروطه الخاصة: جسور اصطلاحية لـ Laravel وSymfony وCodeIgniter، إضافةً إلى مسار مستقل لشيفرة تعمل في أيٍّ منها. نموذج المستند مشترك. ولا يتغيّر سوى طريقة استدعائه.
لماذا يهمّ هذا
قسم بعنوان «لماذا يهمّ هذا»مكتبة PDF مختلفة لكل بنية ضريبةٌ خفيّة. فلكلٍّ منها غرائبها، ومعالجتها الخاصة للخطوط، وفكرتها الخاصة عمّا يعنيه أن يكون الملف صالحًا. فقد تُعرَض فاتورة بشكل صحيح من خدمة Laravel بينما تُعرَض على نحو مختلف خفيًّا من عامل Symfony، لأنّ مكتبةً مختلفة رسمتها. وعندئذٍ يعتمد هدف الأرشفة لديك، وموضع التوقيع، ووسوم إتاحة الوصول، على أيّ فريقٍ شحن المستند. ويقول تقرير الخلل “ملف PDF خاطئ”، وتعتمد الإجابة على أيٍّ من المحرّكات الثلاثة أنتجه.
التوحيد على محرّك واحد يطوي ذلك السطح. فهناك مكان واحد يُقرَّر فيه ملفّ تعريف PDF/A، وأنبوب خطوط واحد يُعتمَد، ومدقّق واحد يُوثَق به. ويكفّ إطار العمل الذي تصادف وجودك فيه عن أن يكون متغيّرًا في ما إذا كان المستند صحيحًا.
الخلاصة الموجزة
قسم بعنوان «الخلاصة الموجزة»- محرّك النواة محايد إزاء أطر العمل. فـ
nextpdf/coreلا يعرف شيئًا عن HTTP، أو التوجيه، أو توصيل الحاوية. إنّه محرّك PDF 2.0 ولا شيء سوى ذلك. - يكيّف كل جسر، ولا يعيد التنفيذ. فحزم Laravel وSymfony و CodeIgniter تمنحك واجهةً أو مصنعًا، ومساعِد استجابة HTTP، ومسار توليدٍ في طابور أو غير متزامن — فوق المحرّك نفسه.
- يتبع الجسر إطار عملك، لا مستندك. فهو يغيّر كيف تستدعي المحرّك، لا ما يستطيع المحرّك إنتاجه أبدًا.
- المسار المستقل متاح دائمًا. فأداة CLI، أو خفيٌّ، أو مكتبةٌ ليس لها إطار عمل لتُجسَر منه؛ بل تبني مستندًا مباشرةً.
- نموذج مستند واحد يسري عبر الأربعة جميعًا. فالكائنات القيمية نفسها، والتعدادات، وعقد المخرَجات، تظهر في كل مكان، فينتقل المستند بين مواضع الاستدعاء من دون تغيير.
كيف يتعامل NextPDF مع ذلك
قسم بعنوان «كيف يتعامل NextPDF مع ذلك»البنية انقسامٌ مقصود. فالمحرّك هو الأصل؛ والجسر مكيِّف رقيق يتكلّم اصطلاحات إطار عملٍ واحد. يسجّل الجسر فضاء أسماء صغيرًا فوق النواة المشتركة عبر التحميل التلقائيّ القياسيّ (Spec: PSR-4 Autoloader, §3PSR-4 Autoloader §3) ويعيد مستندًا عبر عقد الحاوية (Spec: PSR-11 Container, §1.1.2PSR-11 Container §1.1.2). وذلك العقد هو البطل الصامت هنا: فهو يتيح لاستجلابين للمعرِّف نفسه أن يعيدا نُسخًا مختلفة، وهو بالضبط كيف يمنحك الجسر مستندًا جديدًا قابلًا للاستهلاك لكل طلب مع إبقاء سجل الخطوط المُحلَّل ومخبأ الصور كائنين أحاديين على مستوى العملية. فتحصل العمالة الطويلة العمر — Octane وRoadRunner وSwoole وMessenger — على تحليلِ خطوطٍ مُستهلَك الكلفة دون أيّ تسرّب لحالةٍ بين الطلبات، بحكم البناء.
تختلف الاصطلاحات الأربعة على السطح فقط:
- Core enginenextpdf/core — the framework-agnostic PDF 2.0 engine; the single shared document model, value objects, and output contract.
- Laravel bridgenextpdf/laravel — auto-discovered provider, a Pdf facade, a PdfResponse helper, and a queued GeneratePdfJob.
- Symfony bridgenextpdf/symfony — an auto-registered bundle, an injectable PdfFactory, a PdfResponse, and an optional Messenger handler.
- CodeIgniter bridgenextpdf/codeigniter — a service and pdf() helper, a Pdf library over a disposable Document, and a PdfResponse.
- StandaloneNo framework to bridge from — construct a Document directly in a CLI tool, daemon, or library.
اقرأ المخطّط من اليسار إلى اليمين فيكون الدرس هو التماثل. فكل سطح
يؤول إلى الـDocument نفسه. وواجهة Laravel، ومصنع Symfony،
وخدمة CodeIgniter، والبانِي المستقل، أربعة أبواب إلى غرفة
واحدة.
مثال عملي
قسم بعنوان «مثال عملي»النيّة نفسها في ثلاثة أسطر، معبَّرٌ عنها في كل اصطلاح. والجسم الذي يبني المستند — صفحات، وخطوط، وخلايا، وتوقيع، وتوافق — متطابق في الأربعة جميعًا، لأنّه المحرّك نفسه.
<?php
declare(strict_types=1);
// Laravel — resolve a fresh document from the container.use NextPDF\Contracts\PdfDocumentInterface;$document = app(PdfDocumentInterface::class);
// Symfony — inject the factory, then ask it for a document.use NextPDF\Symfony\Service\PdfFactory;$document = $factory->create(); // PdfFactory injected into your service
// CodeIgniter — pull it from the Services layer.use NextPDF\CodeIgniter\Config\Services;$document = Services::pdfDocument();
// Standalone — no framework; construct it directly.use NextPDF\Core\Document;$document = Document::createStandalone();
// From here, the code is identical regardless of how $document arrived.$document->addPage();$document->cell(0, 10, 'One engine, every framework', newLine: true);$bytes = $document->getPdfData();الأسطر الأولى هي الفارق الوحيد. وكل ما بعدها قابل للنقل: انقل خدمة بناء مستند من Symfony إلى عامل مستقل ولن تتغيّر شيفرة التصيير، لأنّ العقد الذي تعتمد عليه لم يتغيّر.
مفهوم خاطئ شائع
قسم بعنوان «مفهوم خاطئ شائع»الافتراض المتكرّر هو أنّ جسر إطار العمل يُتيح قدرات —
أنّ التحقّق طويل الأمد من التوقيع أو الفوترة الإلكترونية المهيكلة يصل لأنّك
ثبّتّ nextpdf/laravel بدلًا من استدعاء المحرّك مباشرةً. وهو لا
يفعل. فالجسر يغيّر موضع الاستدعاء، لا مدى المحرّك أبدًا. والقدرات
الأساسية مثل مخرَجات PDF/A وتوقيع PAdES الأساسي مفتوحة المصدر
وتصل إلى كل سطح؛ أمّا القدرات المتقدّمة فيُتيحها إصدارٌ وتصبح حينها
متاحة عبر أيّ جسر أو المسار المستقل على حدٍّ سواء.
اختيار تكامل إطار العمل ليس اختيارًا لمجموعة ميزات.
والمفهوم الخاطئ المقابل هو أنّ “محرّكًا واحدًا” يجب أن يعني مسار تصيير واحدًا لكل مستند. وهو لا يعني ذلك. فالمحرّك داخل العملية يصيّر PDF مباشرةً؛ وحين يحتاج مستندٌ حقًّا إلى محرّك تخطيطٍ من فئة المتصفّح، تتولّى ذلك حزمة تصيير. والتصيير والاستدعاء محوران منفصلان — و دليل قرار التكامل هو المكان الذي يربطهما.
الحدود والقيود
قسم بعنوان «الحدود والقيود»الجسر لا يوسّع ما يستطيع المحرّك تصييره. وذلك هو الحدّ الأمين، وهو المغزى: القدرة تعيش في النواة والفئة، لا في المكيِّف الذي تبلغها عبره.
| Edition | Availability |
|---|---|
| Core | كل جسر (Laravel وSymfony وCodeIgniter) والمسار المستقل بترخيص Apache-2.0 ويعمل مقابل Core. فهي تكيّف المحرّك أو تعرضه؛ وهي لا تحجب الميزات ولا تغيّر ما يستطيع إنتاجه. |
| Pro | تُتاح القدرات المتقدّمة مثل التحقّق طويل الأمد من التوقيع (PAdES B-LT وB-LTA) بإصدار، ثم تُبلَغ على نحو متطابق عبر أيّ جسر أو المسار المستقل — لا بتبديل إطار العمل أبدًا. ومخرَجات أرشفة PDF/A وتوقيع PAdES الأساسي (B-B وB-T) موجودة أصلًا في Core، متاحة بالطريقة نفسها عبر كل سطح. |
| Enterprise | الفوترة الإلكترونية المهيكلة (EN 16931) وأدوات الامتثال الأعمق قدرات إصدارٍ كذلك، وهي كذلك متطابقة أيًّا كان السطح الذي يستدعي المحرّك، بينما يُشحَن التحقّق من التوافق نفسه في Core. |
ثمة حدّان آخران جديران بالقول صراحةً. أولًا، يتتبّع كل جسر إصدارًا رئيسيًّا حاليًّا من إطار عمله — فـLaravel وSymfony وCodeIgniter يثبّت كلٌّ منها نطاقًا مدعومًا، فيعني “لكل إطار عمل” الإصدار المدعوم من كلٍّ منها، لا كل إصدار تاريخيّ؛ وعامِل توثيق كل حزمة بوصفه المرجع لواجهتها البرمجية. ثانيًا، الجسور مكيّفات أطر عمل، لا خلفيات تصيير. فإذا احتاج مستندٌ إلى محرّك تخطيط متصفّح كامل، فذلك اختيار تصيير مستقل عن أيّ إطار عمل استدعى المحرّك.
مستندات ذات صلة
قسم بعنوان «مستندات ذات صلة»- دليل قرار التكامل — خريطة حالة الاستخدام إلى الحزمة، شاملةً المصيّرات وسطح خدمة Connect، حين تحتاج إلى أن تقرّر بدلًا من أن توحّد.
- نواة مفتوحة، بلا احتجاز — لماذا المحرّك هو الأصل والجسور رقيقة، فلا يحبسك التوحيد.
- أنبوب HTML — ما الذي يغطّيه المحرّك داخل العملية، لتعرف متى يكون مصيّر المتصفّح سؤالًا منفصلًا.
- أُسُس PHP 8.4 — أرضية وقت التشغيل التي يتشاركها كل جسر والمسار المستقل.
مسرد المصطلحات
قسم بعنوان «مسرد المصطلحات»- محرّك النواة —
nextpdf/core، محرّك PDF 2.0 المحايد إزاء أطر العمل الذي يبني عليه كل جسر والمسار المستقل. - جسر إطار العمل — حزمة تكامل (Laravel وSymfony و CodeIgniter) تكيّف المحرّك مع اصطلاحات إطار عمل — واجهة، ومصنع، واستجابة، ومهمّة في طابور — دون تغيير قدراته.
- المسار المستقل — استخدام محرّك النواة مباشرةً، دون إطار عمل، ببناء
Documentبنفسك؛ وهو الطريق لأدوات CLI، والخفيّات، و المكتبات. - المستند القابل للاستهلاك — عقد
Documentذو الاستخدام الواحد: ابنِ، وأصدِر، وتخلَّص. ويعيد كل استجلابِ حاويةٍ مستندًا جديدًا، فلا تتسرّب حالة بين الطلبات في عاملٍ طويل العمر. - PAdES — التواقيع الإلكترونية المتقدّمة لـPDF، عائلة ملفّات تعريف ETSI لتوقيع PDF. والتوقيع الأساسي (B-B وB-T) في Core؛ والتحقّق طويل الأمد (B-LT وB-LTA) قدرة من فئة الإصدار المتقدّم. وأيٌّ منهما يُبلَغ عبر أيّ سطح، ويُتناول بعمق في صفحات التوقيع.