استكشاف أخطاء NextPDF لـ Laravel وإصلاحها
لمحة سريعة
قسم بعنوان «لمحة سريعة»استخدم هذه الصفحة لربط كل عطل ظاهر في الحزمة بسببه الجذري المُتحقَّق منه على مستوى المصدر. يوضّح كل مدخل العَرَض والسبب والإصلاح.
التثبيت
قسم بعنوان «التثبيت»composer require nextpdf/laravelphp artisan vendor:publish --tag=nextpdf-configنظرة مفاهيمية عامة
قسم بعنوان «نظرة مفاهيمية عامة»تقع معظم المشكلات المُبلَّغ عنها ضمن خمس مجموعات: الاكتشاف، وحلّ الحاوية، والتوقيع، ومهام الطابور، وأسماء ملفات بروتوكول نقل النص الفائق (HTTP). تفشل الحزمة بوضوح وعن قصد. تُعيد الميزات الاختيارية غير المُهيّأة القيمة null، بينما يرفع الإدخال غير الآمن استثناءات مُحدَّدة النوع. غالبًا ما يشير العَرَض مباشرةً إلى السبب.
سطح API — من العَرَض إلى السبب
قسم بعنوان «سطح API — من العَرَض إلى السبب»الاكتشاف والإقلاع
قسم بعنوان «الاكتشاف والإقلاع»| العَرَض | السبب المُتحقَّق منه | الإصلاح |
|---|---|---|
| مزوّد الخدمة غير مُسجَّل بعد التثبيت | يعطّل التطبيق الاكتشاف عبر extra.laravel.dont-discover | أزِل الحزمة من dont-discover، أو سجِّل NextPdfServiceProvider يدويًا في bootstrap/providers.php |
config('nextpdf') فارغ | لم تُدمج التهيئة لأنه لم يُحَلّ أي ربط مُعلَن عنه (مزوّد مؤجَّل) | حُلّ أي مدخل في provides()، أو تحقّق من الاكتشاف عبر php artisan package:discover --ansi |
config/nextpdf.php لم يُنشَأ عند النشر | عدم تطابق وسم النشر | استخدم الوسم الدقيق: php artisan vendor:publish --tag=nextpdf-config |
| RuntimeException: “يتطلّب NextPDF امتداد PHP ext-mbstring/ext-zlib“ | امتداد PHP مطلوب مفقود في وقت التشغيل | ثبِّت أو فعِّل mbstring وzlib في php.ini |
حلّ الحاوية
قسم بعنوان «حلّ الحاوية»| العَرَض | السبب المُتحقَّق منه | الإصلاح |
|---|---|---|
app(SignerInterface::class) يُعيد null | التوقيع مُعطَّل، أو الشهادة فارغة في nextpdf.signature | اضبط signature.enabled = true وشهادة صالحة في signature.certificate؛ وثبِّت nextpdf/premium لتوفير الصنف المُجسَّد للموقِّع |
app(TsaClient::class) يُعيد null | nextpdf.tsa.url فارغ | هيِّئ tsa.url (وcredentials/pins حسب الحاجة) |
| تعذّر العثور على الصنف لنوع إصدار PDF/A | nextpdf.pdfa ليس null لكن nextpdf/premium غير مثبَّتة | ثبِّت nextpdf/premium، أو أعِد ضبط pdfa إلى null |
| تعذّر العثور على الصنف عند حلّ عقد فاتورة إلكترونية | الروابط مُسجَّلة، لكن الأصناف المُجسَّدة في Premium غائبة | ثبِّت nextpdf/premium؛ تُحَلّ عقود الفاتورة الإلكترونية بشكل كسول وتفشل فقط عند أول عملية حلّ دون Premium |
| تعديل المستند نفسه عبر عمليتين منطقيتين | ربط المستند مصنع؛ أعدتَ استخدام نسخة واحدة مُحَلّة | حُلّ نسخة جديدة من PdfDocumentInterface لكل مستند |
تطرح الحاوية التي لا تحتوي على مدخل استثناء عدم العثور عند get() (توصية معيار PHP رقم 11 (PSR-11) §1.1.2). عقود الفاتورة الإلكترونية مربوطة، لذلك تُعيد has() الخاصة بالحاوية القيمة true. يرفع الصنف المُجسَّد المفقود في Premium الخطأ في وقت الإنشاء، لا من الحاوية نفسها.
مهام الطابور
قسم بعنوان «مهام الطابور»| العَرَض | السبب المُتحقَّق منه | الإصلاح |
|---|---|---|
InvalidArgumentException: Path traversal sequences are not allowed | مسار الإخراج يحتوي على مقطع .. | استخدم مسارًا مطلقًا خاليًا من الاجتياز ضمن دليل التخزين لديك |
InvalidArgumentException: Stream wrappers are not allowed | المسار يستخدم مخطَّطًا مثل php:// | استخدم مسار نظام ملفات عاديًا |
InvalidArgumentException: Output path contains null bytes | المسار يحتوي على بايت \0 | نقِّ المسار قبل الإرسال |
InvalidArgumentException: Output path must end with .pdf extension | المسار لا ينتهي بـ .pdf (غير حسّاس لحالة الأحرف) | استخدم لاحقة .pdf (أو .PDF) |
| المهمة تعمل لكن الملف فارغ أو خاطئ | مُغلِّفة الباني لم تُعِد المستند المُهيّأ | أعِد المستند من الباني؛ فالمهمة تحفظ القيمة المُعادة |
| المهمة تستخدم الطابور أو المهلة الخاطئة | nextpdf.queue.* غير مضبوط كما هو متوقَّع | اضبط queue.queue وqueue.connection وqueue.timeout؛ يتطلّب tries وbackoff الاشتقاق إلى صنف فرعي |
تُنفَّذ فحوص المسار داخل handle() على العامل، لذلك يفشل المسار الخاطئ أثناء التنفيذ، لا عند الإرسال. هذا مقصود: يتحقّق العامل من حمولة الطابور المُسلسَلة في الموضع الذي يستهلكها فيه.
استجابات HTTP وأسماء الملفات
قسم بعنوان «استجابات HTTP وأسماء الملفات»| العَرَض | السبب المُتحقَّق منه | الإصلاح |
|---|---|---|
اسم ملف التنزيل هو document.pdf بشكل غير متوقَّع | مرّرتَ اسم ملف فارغًا؛ لذلك يستخدم المصنع الاسم الافتراضي | مرِّر اسم ملف غير فارغ |
| اسم الملف فقد مساره أو محارفه الخاصة | يُزيل مُنقّي اسم الملف فواصل المسار، ومحارف التحكّم، والبايتات الصفرية | مرِّر اسم الملف الأساسي فقط؛ هذا التحصين متوقَّع |
| اسم الملف غير ASCII يظهر مشوَّهًا (mojibake) في بعض العملاء | تُصدِر الاستجابة طلب التعليقات 5987 (RFC 5987) filename*= لأسماء غير ASCII؛ يقرأ العملاء القدامى البديل بترميز ASCII | متوقَّع؛ وفّر اسمًا آمنًا بترميز ASCII إذا كان لا بد لعميل قديم أن يطابق تمامًا |
الاستجابة المتدفّقة لا تحتوي على Content-Length | تُغفِل الاستجابات المتدفّقة Content-Length عن قصد (إخراج مُجزَّأ) | متوقَّع؛ استخدم inline()/download() غير المتدفّقتين إذا كان ترويسة الطول مطلوبة |
عيّنة كود — تشخيصات
قسم بعنوان «عيّنة كود — تشخيصات»# Confirm the provider is discoveredphp artisan package:discover --ansi
# Inspect merged configurationphp artisan tinker --execute="dump(config('nextpdf.queue'));"<?php
declare(strict_types=1);
use NextPDF\Contracts\SignerInterface;
$signer = app(SignerInterface::class);
if ($signer === null) { // Signing not configured, or nextpdf/premium not installed. // Continue without a signature, or fail with a clear message.}الحالات الحدّية والمزالق
قسم بعنوان «الحالات الحدّية والمزالق»- مع المزوّد المؤجَّل، قد يبدو التثبيت الجديد “مُعطَّلًا” حتى أول عملية حلّ ذات صلة. عُدّ ظهور الحزمة في قائمة
package:discoverمؤشرًا على النجاح. - عندما يكون
image_cache_mb = null، تتراجع الحزمة إلى 50 ميجابايت؛ القيمة0وحدها تُعطِّل المخبأ. عادةً ما يكون البلاغ عن “عدم تعطُّل المخبأ” قد استخدمnull. - عندما يكون
signature.level = null، تتراجع الحزمة بصمت إلى التواقيع الإلكترونية المتقدمة لـ PDF (PAdES) B-B. عادةً ما يعني البلاغ عن “B-B غير متوقَّع” أن المستوى تُرك من دون ضبط.
الأداء
قسم بعنوان «الأداء»إذا كانت الطلبات الأولى على عامل طويل العمر بطيئة، فذلك لأن سجلّ الخطوط يُحلَّل عند الطلب. عبِّئ nextpdf.preload_fonts كي تُشغَّل عملية الإحماء مرة واحدة عند إقلاع العامل. راجع /integrations/laravel/configuration/ و/integrations/laravel/boot-and-discovery/ للتفاصيل.
ملاحظات أمنية
قسم بعنوان «ملاحظات أمنية»رفض المسارات وأسماء الملفات ضوابط أمنية، وليس أعطالًا. لا تتحايل عليها بفكّ الترميز المُسبق أو بتخفيف الفحوص. وبدلًا من ذلك، وجِّه إخراج الملفات عبر مسار تخزين مُتحكَّم فيه. راجع /integrations/laravel/security-and-operations/.
المطابقة
قسم بعنوان «المطابقة»| الادّعاء | المصدر | البند | reference_id |
|---|---|---|---|
| مدخل الحاوية المفقود يطرح عدم العثور عند get() | حاوية PSR-11 | §1.1.2 |
انظر أيضًا
قسم بعنوان «انظر أيضًا»- /integrations/laravel/install/ — خطوات الاكتشاف والنشر
- /integrations/laravel/configuration/ — كل مفتاح وقيمته الافتراضية
- /integrations/laravel/production-usage/ — حقن التبعيات (DI) وأنماط الطابور
- /integrations/laravel/security-and-operations/ — لماذا توجد فحوص المسار