تخطَّ إلى المحتوى

نظرة عامة على تكامل NextPDF مع Laravel

تصل حزمة nextpdf/laravel محرّك ⁨PDF⁩ الخاص بـ ⁨NextPDF⁩ بتطبيقك على ⁨Laravel 12⁩، وتسجّل روابط الحاوية نيابةً عنك. وتتضمّن واجهة Pdf، ومساعد ⁨HTTP⁩ باسم PdfResponse، ومهمة في الطابور باسم GeneratePdfJob. يكتشف ⁨Laravel⁩ الحزمة تلقائيًّا، لذلك لا تحتاج إلى تسجيلها يدويًّا.

Terminal window
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⁩ فيه.

يتتبّع المخطّط أدناه مسار الطلب من شِفرة تطبيقك، مرورًا بالحزمة، وصولًا إلى سجلّات النواة المشتركة.

NextPDF Laravel request and render flowA request resolves a fresh document from the container, which the package adapts onto the shared font and image registries before HTTP or queue output.

Your Laravel app

Pdf facade

Laravel service container

NextPdfServiceProvider (deferred)

DocumentFactory (singleton)

Document (fresh per resolve)

FontRegistry (singleton, locked)

ImageRegistry (singleton, LRU)

PdfResponse (HTTP)

GeneratePdfJob (queue worker)

NextPDF Laravel request and render flow

تحتوي خريطة التحميل التلقائي على مدخل ⁨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⁩) خالية من تسرّبات الحالة بين الطلبات، مع الاستمرار في توزيع كلفة تحليل الخطوط عبر الطلبات.

الصنفنقطة الدخول العامةيُعيدالغرض
NextPdfServiceProviderregister(), boot(), provides()void / arrayروابط الحاوية، ونشر الإعداد، وقائمة المداخل المؤجّلة
Facades\Pdfوكيل ثابت (addPage()، cell()، save()، …)static / ⁨mixed⁩يحلّ PdfDocumentInterface في كلّ استدعاء
Http\PdfResponseinline(), download(), streamInline(), streamDownload()Response / StreamedResponseاستجابات ⁨HTTP⁩ مع ترويسات من مشروع أمان تطبيقات الويب المفتوح عالميًّا (⁨OWASP⁩)
Jobs\GeneratePdfJobdispatch(), 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
resource: README.md Quick Start (verified against src/Laravel/Facades/Pdf.php)
<?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/.⁩

resource: src/Laravel/Http/PdfResponse.php (download factory)
<?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/⁩ — نموذج التهديد وإعداد النشر