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

إقلاع NextPDF والاكتشاف التلقائي في Laravel

يكتشف ⁨Laravel⁩ تلقائيًا NextPdfServiceProvider من ملف composer.json الخاص بالحزمة. يسجّل المزوِّد روابط الحاوية المؤجَّلة، وينشر ملف الإعداد عند التشغيل في سياق الطرفية (⁨console⁩). توضّح هذه الصفحة آلية الاكتشاف ومدة حياة كل ربط.

Terminal window
composer require nextpdf/laravel
php artisan vendor:publish --tag=nextpdf-config

كيف يعمل الاكتشاف التلقائي في ⁨Laravel⁩

قسم بعنوان «كيف يعمل الاكتشاف التلقائي في ⁨Laravel⁩»

تُعلِن الحزمة عن مزوِّدها والاسم المستعار للواجهة (⁨facade alias⁩) داخل كتلة extra.laravel في ملف composer.json الخاص بها:

resource: composer.json (extra.laravel)
{
"extra": {
"laravel": {
"providers": [
"NextPDF\\Laravel\\NextPdfServiceProvider"
],
"aliases": {
"Pdf": "NextPDF\\Laravel\\Facades\\Pdf"
}
}
}
}

عند تشغيل composer require، يقرأ ⁨Laravel⁩ هذه الكتلة ثم يسجّل المزوِّد والاسم المستعار. لا تحتاج إلى تحرير config/app.php أو bootstrap/providers.php يدويًا. تتولى extra.laravel.providers تسجيل مزوِّدات الخدمة تلقائيًا، وتتولى extra.laravel.aliases تسجيل الأسماء المستعارة للواجهات تلقائيًا (دليل تطوير الحزم في ⁨Laravel 12⁩، https://laravel.com/docs/12.x/packages، استُرجِع في 2026-05-18).

يُطبِّق NextPdfServiceProvider الواجهة DeferrableProvider ودورة الحياة القياسية register() / boot().

  1. register() يدمج إعداد الحزمة تحت المفتاح nextpdf. ثم يربط مدخلات الحاوية: سجل الخطوط، وسجل الصور، ومصنع المستندات، وعميل بروتوكول نقل النص التشعبي (⁨HTTP⁩) وفق توصية معايير ⁨PHP⁩ رقم 18 (⁨PSR-18⁩)، وعميل الطابع الزمني، والموقِّع، والمستند، وعقود الفاتورة الإلكترونية. كل ربط عبارة عن إغلاق (⁨closure⁩)، لذلك لا يُنشأ أي كائن ثقيل هنا.
  2. boot() يتحقق من تحميل امتدادي ⁨PHP⁩، وهما mbstring وzlib. ويسجّل الإعداد القابل للنشر تحت الوسم nextpdf-config فقط عندما تكون قيمة runningInConsole() صحيحة (⁨true⁩).

لأن المزوِّد مؤجَّل، لا يُشغَّل register() إلا عند تحليل (⁨resolve⁩) أحد المدخلات التي تُرجِعها provides(). تحليل مفتاح حاوية غير ذي صلة لا يطلق إقلاع ⁨NextPDF.⁩

تسمح توصية معايير ⁨PHP⁩ رقم 11 (⁨PSR-11⁩) بأن يُرجِع استدعاءان متعاقبان لـ get() بالمعرِّف نفسه قيمًا مختلفة بحسب استراتيجية الربط (⁨PSR-11⁩ §1.1.2). يعتمد المزوِّد على هذا السلوك تصميميًا:

مفتاح الربطالعمرملاحظات
FontRegistryInterface (+ الاسم المستعار FontRegistry)مفرد (⁨singleton⁩)، مُقفَل بعد التهيئة المسبقةمُهيَّأ مسبقًا من preload_fonts؛ مُقفَل حتى لا يستطيع أي طلب تغييره
ImageRegistryمفرد (⁨singleton⁩)ذاكرة تخزين مؤقت محدودة بسياسة الأقل استخدامًا حديثًا (⁨LRU⁩) يُحدَّد حجمها بواسطة image_cache_mb؛ غير مُقفَلة
DocumentFactoryInterface (+ الاسم المستعار DocumentFactory)مفرد (⁨singleton⁩)عديم الحالة؛ يشارك السجلَّين معًا
Psr\Http\Client\ClientInterfaceمفرد (⁨singleton⁩)عميل واعٍ بتزوير الطلبات يغلِّف عميل ⁨curl⁩؛ يُنشأ من tsa.*
TsaClientمُنطاق (⁨scoped⁩)null حين تكون tsa.url فارغة
SignerInterfaceمصنع (⁨factory⁩)null حين يكون التوقيع معطَّلًا أو الشهادة فارغة
PdfDocumentInterface (+ الاسم المستعار nextpdf)مصنع (⁨factory⁩)مستند NextPDF\Core\Document جديد عند كل تحليل، مع تطبيق البيانات الوصفية الافتراضية
EmbedderInterface، ValidatorInterface، ProfileInterface، SchematronRunnerInterfaceمصنع (⁨factory⁩)تُحلَّل إلى التطبيقات الفعلية في ⁨Premium⁩؛ خطأ عند أول تحليل دون nextpdf/premium

يُطبِّق ربط المستند defaults.creator وdefaults.language، وdefaults.author حين لا تكون فارغة، على كل مستند جديد. عندما تكون pdfa غير معدومة (⁨non-null⁩)، فإنها تُفعِّل ⁨PDF/A⁩ (⁨Premium⁩). وعندما يكون القسم artisan موجودًا وكان صنف مصنع متصفح ⁨Chrome⁩ موجودًا، فإنها تُطبِّق إعداد مُصيِّر ⁨Chrome.⁩

تأخذ has() على الحاوية معرِّفًا نصيًّا واحدًا (⁨PSR-11⁩ §1.1.2). عقود الفاتورة الإلكترونية مربوطة، لذلك تُرجِع has() القيمة صحيحة (⁨true⁩) لها حتى عند غياب ⁨Premium.⁩ لا يظهر الخطأ المتعلق بالتطبيق الفعلي المفقود إلا عند الإنشاء.

أضِف الحزمة إلى مصفوفة dont-discover في التطبيق، ثم سجّل المزوِّد يدويًا:

resource: application composer.json
{
"extra": {
"laravel": {
"dont-discover": ["nextpdf/laravel"]
}
}
}
resource: bootstrap/providers.php
<?php
declare(strict_types=1);
return [
App\Providers\AppServiceProvider::class,
NextPDF\Laravel\NextPdfServiceProvider::class,
];

يُحلَّل كل مفتاح بهذا الترتيب: متغير البيئة ← قيمة config/nextpdf.php المنشورة ← القيمة الافتراضية للحزمة المدموجة عند register(). تقبل معظم المفاتيح إما اسمًا من نوع NEXTPDF_* أو اسم بيئة قديمًا من نوع TCPDF_*. يُفضَّل استخدام NEXTPDF_*.

Terminal window
php artisan package:discover --ansi

يؤكِّد السطر الذي يُدرِج nextpdf/laravel حدوث الاكتشاف. لأن المزوِّد مؤجَّل، لا تظهر الروابط نفسها حتى أول تحليل. سطر الاكتشاف هو إشارة النجاح الصحيحة.

  • لا يُسجَّل نشر الإعداد إلا في سياق الطرفية، لذلك لا يطلقه طلب ويب وحده. شغّل vendor:publish من واجهة سطر الأوامر (⁨CLI⁩).
  • إلى جانب مفاتيح السجل والمصنع وعميل ⁨HTTP⁩ والموقِّع والطابع الزمني والمستند، تتضمّن provides() مفاتيح عقود الفاتورة الإلكترونية الأربعة.
  • قد يبدو التثبيت الجديد خاملًا حتى أول تحليل ذي صلة. هذا هو تصميم المزوِّد المؤجَّل، لا خلل.

register() هو ⁨O⁩(1) لأنه ينشئ إغلاقات فقط. تهيئة سجل الخطوط المسبقة هي ⁨O⁩(⁨f⁩) بالنسبة إلى الخطوط المُحمَّلة مسبقًا، وتُشغَّل مرة واحدة لكل عملية عامل (⁨worker process⁩). يُبقي تأجيل المزوِّد كلفة إنشاء ⁨NextPDF⁩ خارج مسار إقلاع إطار العمل حتى يُستخدَم ربط فعليًا.

يضيّق التصميم المؤجَّل سطح الهجوم أثناء الإقلاع. يمنع سجل الخطوط المُقفَل أي طلب من تغيير حالة الخطوط لطلب آخر في العمّال طويلي الأمد. للاطلاع على التغطية الكاملة للتهديدات، انظر /⁨integrations/laravel/security-and-operations/.⁩

الادعاءالمصدرالبند⁨reference_id⁩
قد تختلف عمليات التحليل المتعاقبة حسب استراتيجية الربط⁨PSR-11 Container⁩§1.1.2
has() تأخذ معرِّفًا نصيًّا واحدًا⁨PSR-11 Container⁩§1.1.2

يؤكِّد التوثيق الرسمي لحزم ⁨Laravel 12⁩ أسماء مفاتيح الاكتشاف في ⁨Laravel⁩ (https://laravel.com/docs/12.x/packages، استُرجِع في 2026-05-18).

تُحلَّل التطبيقات الفعلية في ⁨Premium⁩ عبر مفاتيح الربط المؤجَّل نفسها. لا تتطلّب هذه القدرة الاختيارية في إصدار ⁨Enterprise⁩ أي تغيير في الشيفرة داخل حزمة ⁨Core⁩ الموثَّقة هنا. انظر https://nextpdf.dev/get-license/?intent=laravel-signing.

  • /⁨integrations/laravel/install/⁩ — التثبيت والنشر
  • /⁨integrations/laravel/overview/⁩ — معمارية الحزمة
  • /⁨integrations/laravel/integration/⁩ — دليل التوصيل من طرف إلى طرف
  • /⁨integrations/laravel/configuration/⁩ — كل مفتاح إعداد