نظرة عامة على تكامل NextPDF مع Laravel
نظرة سريعة
قسم بعنوان «نظرة سريعة»تصل حزمة nextpdf/laravel محرّك PDF الخاص بـ NextPDF بتطبيقك على Laravel 12، وتسجّل روابط الحاوية نيابةً عنك. وتتضمّن واجهة Pdf، ومساعد HTTP باسم PdfResponse، ومهمة في الطابور باسم GeneratePdfJob. يكتشف Laravel الحزمة تلقائيًّا، لذلك لا تحتاج إلى تسجيلها يدويًّا.
التثبيت
قسم بعنوان «التثبيت»composer require nextpdf/laravelقيد Composer هو nextpdf/core: ^3.0 || ^5.2. وتتطلّب الحزمة أيضًا
laravel/framework: ^12.0 وphp: >=8.4 <9.0. للاطّلاع على الإجراء الكامل، بما في ذلك نشر الإعدادات والإضافات الاختيارية، راجِع /integrations/laravel/install/.
نظرة عامة مفاهيمية
قسم بعنوان «نظرة عامة مفاهيمية»تتموضع الحزمة بين حاوية خدمات Laravel ونواة NextPDF المستقلّة عن إطار العمل. وهي لا تعيد تنفيذ توليد PDF. بل تكيّف نموذج النواة NextPDF\Core\Document مع دورة حياة Laravel وإعداداته وطوابيره وطبقة HTTP فيه.
يتتبّع المخطّط أدناه مسار الطلب من شِفرة تطبيقك، مرورًا بالحزمة، وصولًا إلى سجلّات النواة المشتركة.
تحتوي خريطة التحميل التلقائي على مدخل PSR-4 واحد. ويُعدّ PSR-4 معيار PHP الموصى به للتحميل التلقائي، وبادئته NextPDF\Laravel\ تُقابِل src/Laravel/. وفق PSR-4، تُقابِل بادئة الفضاء الاسمي دليلًا أساسيًّا، ويُقابِل باقي اسم الصنف مسار ملف داخل ذلك الدليل (PSR-4 §3). توجد أربعة أصناف إنتاجية تحت هذه البادئة:
NextPDF\Laravel\NextPdfServiceProvider— يسجّل الروابط وينشر الإعدادات.NextPDF\Laravel\Facades\Pdf— وكيل ثابت يحلّ مستندًا جديدًا من الحاوية.NextPDF\Laravel\Http\PdfResponse— ينشئ استجابات PDF مضمّنة، وللتنزيل، ومتدفّقة مع مجموعة ثابتة من ترويسات الأمان.NextPDF\Laravel\Jobs\GeneratePdfJob— مهمة قابلة للوضع في الطابور تبني ملف PDF وتحفظه على عامل.
يُنفّذ مزوّد الخدمة الواجهة DeferrableProvider، لذا لا يسجّل روابطه إلا عند حلّ أحد المداخل المُعلَنة. يُبقي هذا التأجيل مسار إقلاع إطار العمل خفيفًا. تُدرِج دالّة provides() في المزوّد المداخل المؤجّلة، وتقرأ الحاوية هذه القائمة لربط كلّ مفتاح بالمزوّد مجدّدًا.
يتبع الحلّ عقد الحاوية: عند وجود رابط، يُعيد حلّ المعرّف المدخل المُسجَّل. ويُعدّ PSR-11 معيار PHP الموصى به لقابلية التشغيل البيني للحاويات، وهو يوضّح أنّ استدعاءَين متتاليَين لـ get() بالمعرّف نفسه قد يُعيدان قيمتَين مختلفتَين، تبعًا لاستراتيجية الربط (PSR-11 §1.1.2). يعتمد NextPDF على هذا السلوك عمدًا. السجلّات وحيدة (singletons)، لذا يُعيد كلّ حلّ المثيل نفسه. أمّا المستندات فمربوطة بمصنع، لذا يُعيد كلّ حلّ مثيلًا جديدًا. للاطّلاع على جدول دورة حياة الربط الكامل، راجِع /integrations/laravel/boot-and-discovery/.
صُمّمت البنية للعمّال طويلي العمر، مثل Octane وRoadRunner وSwoole. سجلّ الخطوط وحيد بعمر العملية: تسخّنه الحزمة مرّة واحدة ثمّ تقفله، بحيث لا يستطيع أيّ طلب تغيير حالة الخطوط المشتركة. وسجلّ الصور وحيد بعمر العملية، مع ذاكرة مؤقّتة محدودة من النوع الأقل استخدامًا مؤخّرًا (LRU). ولأنّ الحزمة تنشئ كلّ مستند دائمًا من DocumentFactory، فإنّ الحالة القابلة للتغيير الخاصة بكلّ طلب لا تتسرّب أبدًا بين الطلبات.
لماذا تكون المستندات جديدة في كلّ طلب
يُعيد ربط المصنع Document جديدًا في كلّ حلّ، بينما يبقى سجلّا الخطوط والصور المشتركان على مستوى العملية. يُبقي هذا الفصل عمليات العمّال طويلة العمر (Octane وRoadRunner وSwoole) خالية من تسرّبات الحالة بين الطلبات، مع الاستمرار في توزيع كلفة تحليل الخطوط عبر الطلبات.
سطح الـ API
قسم بعنوان «سطح الـ API»| الصنف | نقطة الدخول العامة | يُعيد | الغرض |
|---|---|---|---|
NextPdfServiceProvider | register(), boot(), provides() | void / array | روابط الحاوية، ونشر الإعداد، وقائمة المداخل المؤجّلة |
Facades\Pdf | وكيل ثابت (addPage()، cell()، save()، …) | static / mixed | يحلّ PdfDocumentInterface في كلّ استدعاء |
Http\PdfResponse | inline(), download(), streamInline(), streamDownload() | Response / StreamedResponse | استجابات HTTP مع ترويسات من مشروع أمان تطبيقات الويب المفتوح عالميًّا (OWASP) |
Jobs\GeneratePdfJob | dispatch(), handle(), then(), catch(), failed() | PendingDispatch / void / self | توليد PDF في الطابور |
مفاتيح الحاوية التي يربطها المزوّد:
| المفتاح | العمر | يحلّ إلى |
|---|---|---|
NextPDF\Contracts\FontRegistryInterface (الاسم البديل FontRegistry) | وحيد، مقفل | NextPDF\Typography\FontRegistry |
NextPDF\Graphics\ImageRegistry | وحيد، محدود بـ LRU | ImageRegistry |
NextPDF\Contracts\DocumentFactoryInterface (الاسم البديل DocumentFactory) | وحيد | NextPDF\Core\DocumentFactory |
Psr\Http\Client\ClientInterface | وحيد | SecurityAwareHttpClient يغلّف CurlHttpClient |
NextPDF\Security\Timestamp\TsaClient | بنطاق | TsaClient أو null عند عدم وجود عنوان URL لسلطة الطابع الزمني (TSA) |
NextPDF\Contracts\SignerInterface | مصنع | DigitalSigner أو null عند تعطيل التوقيع |
NextPDF\Contracts\PdfDocumentInterface (الاسم البديل nextpdf) | مصنع | NextPDF\Core\Document |
NextPDF\Contracts\EInvoice\{Embedder,Validator,Profile,SchematronRunner}Interface | مصنع | يحلّ فقط عند تثبيت nextpdf/premium |
مثال شِفرة — البدء السريع
قسم بعنوان «مثال شِفرة — البدء السريع»<?php
declare(strict_types=1);
use NextPDF\Laravel\Facades\Pdf;
Pdf::addPage();Pdf::cell(0, 10, 'Hello from Laravel', newLine: true);Pdf::save(storage_path('app/hello.pdf'));للاطّلاع على مثال قابل للتشغيل في نطاق وحدة تحكّم، راجِع /integrations/laravel/quickstart/.
مثال شِفرة — الإنتاج
قسم بعنوان «مثال شِفرة — الإنتاج»يحلّ نمط الإنتاج عقد المستند من الحاوية بدلًا من الواجهة، ممّا يُبقي موضع الاستدعاء صريحًا وقابلًا للاختبار. للاطّلاع على وحدة التحكّم الكاملة، بما في ذلك حقن التبعيات (DI) ومعالجة الأخطاء، راجِع /integrations/laravel/production-usage/.
<?php
declare(strict_types=1);
use NextPDF\Contracts\PdfDocumentInterface;use NextPDF\Laravel\Http\PdfResponse;
$document = app(PdfDocumentInterface::class);$document->addPage();$document->cell(0, 10, 'Invoice', newLine: true);
return PdfResponse::download($document, 'invoice.pdf');الحالات الحدّية والمزالق
قسم بعنوان «الحالات الحدّية والمزالق»- مزوّد الخدمة مؤجّل، لذا فإنّ حلّ مفتاح حاوية غير ذي صلة لا يُقلِع NextPDF. لا تظهر الروابط إلا عند طلب أحد مداخل
provides(). - يحلّ
SignerInterfaceوTsaClientإلىnullعمدًا عندما لا تكون قد أعددت التوقيع أو سلطة الطابع الزمني. تحقّق في شِفرتك من القيمة null؛ ولا تفترض وجود مثيل. - روابط عقد الفاتورة الإلكترونية مُسجَّلة دائمًا، لكنّها تحلّ إلى تجسيدات Premium لا توجد إلّا عند تثبيت
nextpdf/premium. حلّها بدون Premium يطلق خطأ عدم العثور على الصنف، ويظهر الخطأ عند أوّل حلّ، لا عند الإقلاع. - تُعيد الواجهة مستندًا جديدًا في كلّ حلّ. عند إجراء استدعاءَين ثابتَين لـ
Pdf::في الطلب نفسه ويفصل بينهماPdf::clearResolvedInstances()، يعمل الاستدعاءان على مستندَين مختلفَين.
تحقّق من null لخدمات التوقيع الاختيارية
يكون SignerInterface وTsaClient بقيمة null إلى أن تُعِدّ التوقيع وسلطة الطابع الزمني، لذا يجب على أيّ شِفرة تحلّ هذه المفاتيح أن تعالج حالة null. غياب التحقّق من null يؤدي إلى فشل عند التشغيل، لا عند الإقلاع.
الأداء
قسم بعنوان «الأداء»يجري تسجيل المزوّد في زمن O(1). يربط المزوّد إغلاقات (closures) ولا يُنشئ كائنات ثقيلة، لذا تُؤجَّل كلفة الإنشاء إلى أوّل حلّ. يجري تسخين سجلّ الخطوط في زمن O(f)، حيث f هو عدد ملفّات الخطوط المُحمَّلة مسبقًا، ويحدث ذلك مرّة واحدة لكلّ عملية عامل. يوزّع هذا كلفة زمن استجابة الطلب الأوّل في العمّال طويلي العمر. ميزانية الذاكرة لكلّ صفحة في هذه النظرة العامة مُسجَّلة في حقل المقدّمة performance_budget.
ملاحظات الأمان
قسم بعنوان «ملاحظات الأمان»يطبّق PdfResponse مجموعة ثابتة من ترويسات مشروع أمان تطبيقات الويب المفتوح عالميًّا (OWASP). تتضمّن المجموعة X-Content-Type-Options: nosniff، وX-Frame-Options: DENY، وContent-Security-Policy: default-src 'none'، وX-Robots-Tag، وReferrer-Policy: no-referrer. يتحقّق GeneratePdfJob من مسار خرجه على جانب العامل، ممّا يخفّف أثر الحُمولات المُسلسَلة التي عُبث بها. للاطّلاع على نموذج التهديد الكامل وإعداد النشر، راجِع /integrations/laravel/security-and-operations/.
حُمولة الطابور مُدخَل غير موثوق
يُعيد GeneratePdfJob التحقّق من مسار الخرج داخل handle() على العامل، لا عند وقت الإرسال فقط. ولأنّ الحُمولة المُسلسَلة يمكن العبث بها على ناقل الطابور (Redis أو قاعدة البيانات) قبل أن يلتقطها العامل، فإنّ الفحص على جانب العامل يرفض اجتياز المسارات، وأغلفة التدفّق (stream wrappers)، والبايتات الصفرية، والأهداف غير PDF.
المطابقة
قسم بعنوان «المطابقة»| الادّعاء | المصدر | البند | reference_id |
|---|---|---|---|
| حلّ الحاوية / دلالات العمر | حاوية PSR-11 | §1.1.2 | |
| تعيين بادئة التحميل التلقائي PSR-4 | محمّل PSR-4 التلقائي | §3 |
السياق التجاري
قسم بعنوان «السياق التجاري»عند تثبيت nextpdf/premium، يكشف المزوّد نفسه قدرات إضافية: التوقيع الرقمي (PAdES B-B)، وأرشفة PDF/A، وروابط عقد الفاتورة الإلكترونية. ويكشفها عبر مفاتيح الحاوية نفسها، لذا لا تحتاج حزمة Core الموثّقة هنا إلى أيّ تغيير في الشِفرة لتبنّي هذه القدرات. للتفاصيل، راجِع
https://nextpdf.dev/get-license/?intent=laravel-signing.
انظر أيضًا
قسم بعنوان «انظر أيضًا»- /integrations/laravel/install/ — خطوات التثبيت والإضافات الاختيارية
- /integrations/laravel/quickstart/ — مثال وحدة تحكّم قابل للتشغيل
- /integrations/laravel/configuration/ — كلّ مفتاح إعداد، مُتحقَّق منه مقابل
config/nextpdf.php - /integrations/laravel/production-usage/ — وحدة تحكّم موصولة بحقن التبعيات، ومعالجة الأخطاء، ووضع المهام في الطابور
- /integrations/laravel/boot-and-discovery/ — الاكتشاف التلقائي وأعمار الربط
- /integrations/laravel/security-and-operations/ — نموذج التهديد وإعداد النشر