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

استكشاف أخطاء NextPDF وإصلاحها في CodeIgniter 4

يرتبط كل عَرَض أدناه بسبب مُتحقَّق منه في مصدر الحزمة أو إطار العمل، ويتضمّن إصلاحًا عمليًا.

عندما يحلّ ⁨CodeIgniter⁩ خدمةً ما، يفحص فئات Config\Services المُكتشَفة بحثًا عن دالة مطابقة. ويعني إرجاع null أنّ ⁨CodeIgniter⁩ لم يكتشف فئة Services الخاصة بالحزمة.

تحقّق من هذه الأسباب وإصلاحاتها:

  • الاكتشاف التلقائي معطَّل. قد يضبط التطبيق المُضيف Config\Modules::$discoverInComposer = false. إذا كان الأمر كذلك، فأضِف nextpdf/codeigniter إلى $composerPackages['only']. لا يفحص ⁨CodeIgniter⁩ حزم ⁨Composer⁩ إلا عندما تكون قيمة هذا العَلَم true.
  • أداة التحميل التلقائي قديمة. يربط ⁨Composer⁩ بادئة مساحة الأسماء NextPDF\CodeIgniter\ بدليلها الأساسي. وقد تخفي خريطة الفئات القديمة هذه الفئة (⁨PSR-4⁩ §⁨x1.x3⁩). شغّل composer dump-autoload.
  • قائمة $aliases جرى تقليصها. لا يجري الاكتشاف إلا للمدخلات الموجودة في Config\Modules::$aliases. تحتاج الحزمة إلى services وإلى registrars للمساعِدات. استعِد كلا المدخلين.

pdf() أو pdf_document() غير مُعرَّفة

قسم بعنوان «pdf() أو pdf_document() غير مُعرَّفة»

تُحمَّل المساعِدات عبر مسارين: مدخل التحميل التلقائي files في ⁨Composer⁩ الخاص بالحزمة، وRegistrar الخاص بالحزمة. ويعني خطأ الدالة غير المُعرَّفة أنّ مدخل files لم يُحمَّل.

  • شغّل composer dump-autoload لإعادة بناء قائمة التحميل التلقائي files.
  • تأكّد من ظهور nextpdf/codeigniter في vendor/composer/autoload_files.php.
  • إن احتجت إلى حلٍّ بديل، فاستدعِ Services::pdf(false) أو Services::pdfDocument(false) مباشرةً. فالمساعِدات ليست سوى أغلفة خفيفة حول هذه الاستدعاءات.

لحلّ أي تجاوز، تستخدم BaseConfig اسم الفئة القصير بأحرف صغيرة كبادئة. وبما أنّ الفئة هي NextPdf، فالبادئة هي nextpdf، وليست nextPdf ولا NextPdf.

  • استخدم nextpdf.fontsPath، وليس nextPdf.fontsPath.
  • للمفتاح المتداخل، استخدم نقطةً: nextpdf.signature.certificate.
  • يعمل أيضًا الشكل المؤهَّل بالكامل NextPDF\CodeIgniter\Config\NextPdf.fontsPath.

عودة مصفوفة تهيئة كاملة إلى القيم الافتراضية

قسم بعنوان «عودة مصفوفة تهيئة كاملة إلى القيم الافتراضية»

عندما توسِّع الفئة NextPdf وتُسنِد مصفوفة جزئية، يستبدل ⁨CodeIgniter⁩ المصفوفة بأكملها. وفّر كل مفتاح في المصفوفة التي تتجاوزها. وللاطّلاع على مثال لمصفوفة كاملة، راجع /⁨integrations/codeigniter/configuration/.⁩

RuntimeException: NextPDF requires the ext-… PHP extension

قسم بعنوان «RuntimeException: NextPDF requires the ext-… PHP extension»

يتحقّق سِجِل الخطوط من mbstring وzlib مرةً واحدةً لكل عملية. ويطلق هذا الخطأ مع اسم الامتداد المفقود. ثبّت الامتداد المذكور أو فعّله في ⁨PHP⁩ وقت التشغيل، ثم أعِد تشغيل العامل أو تجمُّع مدير عمليات ⁨PHP FastCGI⁩‏ (⁨PHP-FPM⁩).

RuntimeException: NextPdf fontsPath contains invalid characters

قسم بعنوان «RuntimeException: NextPdf fontsPath contains invalid characters»

يرفض سِجِل الخطوط أيّ fontsPath يحتوي على غلاف دفق (://) أو بايت صفري. اضبط fontsPath على مسار عادي في نظام الملفات. لا توجّهه إلى مسار php:// أو phar:// أو أي مسار مُغلَّف مشابه.

اسم الملف يبدو خاطئًا في التنزيل

قسم بعنوان «اسم الملف يبدو خاطئًا في التنزيل»

تطهّر PdfResponse أسماء الملفات. توقّع السلوك المُتحقَّق منه الآتي:

  • يصبح اسم الملف الفارغ أو المؤلَّف من مسافات فقط document.pdf.
  • يُلحَق .pdf بالاسم الذي لا يحمل امتداد .pdf (أو .PDF). ويُحفَظ أيّ امتداد .PDF موجود كما هو.
  • يُنتِج الاسم الذي يحتوي على أحرف غير ⁨ASCII⁩ بديلًا بترميز ⁨ASCII⁩ و معامل ⁨RFC 5987⁩ ‏filename*=UTF-8''…، فتُظهِر المتصفحات الحديثة الاسم الأصلي. هذا سلوك متوقَّع، وليس خللًا.
  • تُزال فواصل المسارات والبايتات الصفرية وحرفا الإرجاع ⁨return/line feed⁩‏ (⁨CR/LF⁩).

الاستجابة تفتقد ترويسات الأمان

قسم بعنوان «الاستجابة تفتقد ترويسات الأمان»

تتضمّن كل PdfResponse الترويسات X-Content-Type-Options وX-Frame-Options وContent-Security-Policy وX-Robots-Tag وReferrer-Policy. إذا كانت غائبة عند العميل، فهذا يعني أنّ وكيلًا أو التطبيق يزيلها أو يكتب فوقها في مرحلة لاحقة. افحص الاستجابة قبل الوكيل العكسي وبعده.

تتحقّق قائمة الانتظار من اسم المهمة المدفوعة بمقارنته بالمفاتيح الموجودة في Config\Queue::$jobHandlers، وترفض أيّ اسم غير مُسجَّل. سجّل المهمة تحت مفتاح اسم، ثم ادفع ذلك الاسم:

app/Config/Queue.php
public array $jobHandlers = ['generate-pdf' => GeneratePdfJob::class];
// dispatch
\service('queue')->push('pdf-queue', 'generate-pdf', [...]);

يفشل دفع GeneratePdfJob::class كاسم للمهمة؛ فالوسيط الثاني هو مفتاح اسم، وليس سلسلة فئة.

تتحقّق المهمة من حمولتها قبل تنفيذ أي عمل. وتُعيد حالات الرفض المُتحقَّق منها أجزاء الرسائل التالية:

السببجزء الرسالة
builder مفقود أو فارغ أو ليس سلسلة نصيةnon-empty static callable string
builder خارج App\PdfBuildersnot allowed
builder يطابق النمط لكنه ليس قابلًا للاستدعاءnot a valid callable
outputPath مفقود أو فارغnon-empty string
outputPath خارج WRITEPATH/pdfs/outside of allowed directory
outputPath لا ينتهي بـ .pdfmust end with .pdf

أصلِح الحمولة بحيث يكون المُنشئ قابلًا للاستدعاء الساكن App\PdfBuilders\<Class>::<method>. تأكّد من أنّ مسار الإخراج يُحلّ داخل WRITEPATH/pdfs/ وينتهي بامتداد .pdf.

بما أنّ codeigniter4/queue اعتمادية للتطوير فقط في الحزمة، يجب على التطبيق الذي يشغّل العمّال طلبها مباشرةً:

Terminal window
composer require codeigniter4/queue
  • composer show nextpdf/codeigniter — تأكّد من أنّ ⁨Composer⁩ قد حلّ الحزمة.
  • composer dump-autoload — أعِد بناء الاكتشاف وقائمة التحميل التلقائي للمساعِدات.
  • php spark routes — تأكّد من تسجيل مسارات ⁨PDF⁩ لديك.
  • لإجراء أسرع فحص للاكتشاف، استخدم وحدة تحكُّم تستدعي Services::pdfDocument(false) وتؤكّد أنّ النتيجة هي Document.
  • تخطيط الفئة إلى المسار — ذو صلة بحالات فشل الاكتشاف (⁨PSR-4 Autoloader⁩ §⁨x1.x3⁩).
  • /⁨integrations/codeigniter/install/⁩ — متطلبات الاكتشاف.
  • /⁨integrations/codeigniter/configuration/⁩ — بادئة .env وقاعدة تجاوز المصفوفة.
  • /⁨integrations/codeigniter/production-usage/⁩ — التسجيل الصحيح لقائمة الانتظار.
  • /⁨integrations/codeigniter/boot-and-discovery/⁩ — تسلسل الاكتشاف.