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

استكشاف أخطاء حزمة NextPDF الخاصة بـ Symfony وإصلاحها

تنبع معظم المشكلات من أحد أربعة مجالات: الاكتشاف، أو التحقق من صحة الإعداد، أو ربط الحاوية، أو توجيه ⁨Messenger.⁩ يربط كل قسم العَرَض بسلوك الحزمة الأساسي، ثم يقدّم أمراً طرفياً للتحقق من الإصلاح.

العَرَض: يتعذّر عليك ربط PdfFactory تلقائياً، أو لا يعرض debug:container nextpdf أي شيء.

السبب: لم تُضَف الحزمة إلى config/bundles.php. ربما لم يعمل ⁨Flex⁩، أو ربما لا يستخدم التطبيق ⁨Flex.⁩

الحل:

Terminal window
php bin/console debug:container nextpdf

إذا لم يعرض الأمر أي خدمات، فأضف الحزمة يدوياً:

return [
NextPDF\Symfony\NextPdfBundle::class => ['all' => true],
];

يحتوي ملف composer.json الخاص بالحزمة على تلميح التسجيل التلقائي ضمن extra.symfony.bundles. ولا يسري إلا على التطبيقات التي فُعّل فيها ⁨Flex.⁩

فشل الإقلاع بسبب امتداد ⁨PHP⁩ مفقود

قسم بعنوان «فشل الإقلاع بسبب امتداد ⁨PHP⁩ مفقود»

العَرَض: تطرح النواة RuntimeException يذكر ext-mbstring أو ext-zlib أثناء الإقلاع.

السبب: يأتي ذلك من NextPdfExtension::guardRequiredExtensions()، وهو حارس الفشل السريع المقصود في الحزمة. وهذا ليس خللاً.

الحل: فعّل الامتداد المذكور في php.ini، ثم أعد تشغيل بيئة التشغيل. تحقّق من ذلك باستخدام:

Terminal window
php -m | grep -E 'mbstring|zlib'

العَرَض: يطرح ⁨Symfony⁩ Symfony\Component\Config\Definition\Exception\InvalidConfigurationException أثناء تشغيل cache:clear أو cache:warmup.

السبب: توجد قيمة خارج المخطّط. يعرّف Configuration.php هذه القيود:

  • يجب أن يكون page_format أحد القيم A4 أو A3 أو A5 أو Letter أو Legal أو Tabloid.
  • يجب أن يكون orientation هو P أو L.
  • يجب أن يكون unit أحد القيم pt أو mm أو cm أو in.
  • يجب أن يكون pdfa هو null أو 4 أو 4e أو 4f.
  • يجب أن تكون قيمة image_cache_mb هي >= 0.

الحل: اعرض الإعداد المدمَج، ثم صحّح المفتاح الذي فشل:

Terminal window
php bin/console debug:config nextpdf

العَرَض: ضُبط pdfa أو قسم signature، لكن المخرَج ملف عادي بصيغة المستند المحمولة (⁨PDF⁩).

السبب: تتطلّب هذه القدرات nextpdf/premium. في وقت الترجمة، لا يطبّق PdfFactory صيغة ⁨PDF/A⁩ إلا عند اكتشاف امتداد ⁨Pro.⁩ ولا يسجّل مسار المترجم موقِّعاً إلا عندما يكون signature.enabled صحيحاً و signature.certificate مضبوطاً.

الحل: تأكّد من تثبيت ⁨Premium⁩ ومن وجود خدمة الموقِّع:

Terminal window
composer show nextpdf/premium
php bin/console debug:container --show-private | grep -i signer

إذا لم يكن ⁨Premium⁩ موجوداً، فستخزّن الحزمة الإعداد لكنها تتركه خاملاً عن قصد. قدرة التوقيع الموثّقة للحزمة مع ⁨Pro⁩ هي ملف التعريف الأساسي ⁨B-B.⁩ وتغطّي وثائق ⁨NextPDF Premium⁩ ملفات التعريف التي تتجاوز ⁨B-B.⁩

العَرَض: يُتجاهل إعداد artisan.

السبب: يتطلّب العرض عبر بروتوكول ⁨Chrome DevTools⁩‏ (⁨CDP⁩) امتداد nextpdf/artisan. يفحص مسار المترجم وجوده باستخدام class_exists في وقت الترجمة. إذا لم يكن الامتداد موجوداً، فلن يُربط المُصيِّر.

الحل:

Terminal window
composer show nextpdf/artisan
php bin/console cache:clear # re-run the compile-time probe

يُجرى الفحص أثناء ترجمة الحاوية. بعد تثبيت الامتداد، شغّل cache:clear مرة أخرى.

مُعالج ⁨Messenger⁩ لا يُستدعى أبداً

قسم بعنوان «مُعالج ⁨Messenger⁩ لا يُستدعى أبداً»

العَرَض: ترسل GeneratePdfMessage، لكن لا يُكتب أي ملف ⁨PDF.⁩

الأسباب والحلول:

  • الرسالة غير موجَّهة — أضف مدخل توجيه يربط NextPDF\Symfony\Message\GeneratePdfMessage بناقل في config/packages/messenger.yaml، ثم شغّل عاملاً (php bin/console messenger:consume <transport>).
  • المُنشئ غير موجود في المُحدِّد — يجلب المُعالج المُنشئ من مُحدِّد توصية معايير ⁨PHP⁩ رقم 11‏ (⁨PSR-11⁩) عبر مُعرّف سلسلة الصنف الخاص به. مُعرّف الحاوية سلسلة تعرّف مدخلاً تعريفاً فريداً (⁨PSR-11⁩ §1.1.2). إذا لم يكن صنف المُنشئ مسجّلاً في المُحدِّد، يطرح المُعالج RuntimeException يوضح أن المُنشئ المُعدّ يجب أن يطبّق PdfBuilderInterface. سجّل المُنشئ، ثم أشِر إليه من المُحدِّد.

افحص التوجيه والمُحدِّد:

Terminal window
php bin/console debug:messenger
php bin/console debug:container --tag=container.service_locator

رفض الرسالة عند الإرسال بـ ⁨InvalidArgumentException⁩

قسم بعنوان «رفض الرسالة عند الإرسال بـ ⁨InvalidArgumentException⁩»

العَرَض: يطرح إنشاء GeneratePdfMessage الاستثناء InvalidArgumentException.

السبب: يتحقّق كائن نقل البيانات (⁨DTO⁩) الخاص بالرسالة من صحة مدخلاته. قواعد الرفض المتحقَّق منها هي:

  • مسار مخرَجات فارغ، أو مسار يحتوي على بايت فارغ (⁨null byte⁩)؛
  • مخطّط مُغلِّف دفق (على سبيل المثال php://...
  • مقطع اجتياز مسار .. (بفواصل ⁨POSIX⁩ أو ⁨Windows⁩)؛
  • مسار مخرَجات لا ينتهي بـ .pdf (غير حسّاس لحالة الأحرف)؛
  • قيمة builderClass ليست اسم صنف صحيحاً من الناحية النحوية.

الحل: مرّر مساراً مطلقاً في نظام الملفات ينتهي بـ .pdf واسم صنف مُنشئ فعلياً ومؤهَّلاً بالكامل.

العَرَض: يتضمّن ملف ⁨PDF⁩ مُولَّد محتوى من طلب سابق.

السبب: احتفظ عامل طويل الأمد بنسخة Document بين الطلبات. خدمة المستند غير مشتركة تحديداً لمنع حدوث ذلك.

الحل: استدعِ PdfFactory::create() داخل الطريقة المحصورة بنطاق الطلب. لا تخزّن المستند المُرجَع أبداً في خدمة مشتركة.

Terminal window
php bin/console debug:container nextpdf # bundle services
php bin/console debug:config nextpdf # merged configuration
php bin/console debug:container --show-private # internal definitions
php bin/console debug:messenger # message routing
php bin/console messenger:consume <t> -vv # verbose consume

كل صف هو ادعاء معياري وارد في هذه الصفحة ومثبَّت إلى reference_id كامل من 64 خانة ست عشرية من مجموعة منظمة تطوير المعايير (⁨SDO⁩) المقيَّدة. يوجد المصدر، بما في ذلك بيان المجموعة وناقل الاسترجاع، في _sidecars/rag-citations.yaml.

المواصفةالبند⁨reference_id⁩الادعاء
⁨PSR-11⁩psr_11_container#1.1.2.p4عقد مُعرّف ⁨has⁩()/⁨get⁩() في الحاوية
  • /⁨integrations/symfony/install/⁩ — التثبيت والتسجيل.
  • /⁨integrations/symfony/configuration/⁩ — المخطّط الكامل والقيود.
  • /⁨integrations/symfony/boot-and-discovery/⁩ — تسلسل الاكتشاف والإقلاع.
  • /⁨integrations/symfony/security-and-operations/⁩ — ترويسات الأمان والتحقق من المسارات.