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

استكشاف أخطاء NextPDF لـ Laravel وإصلاحها

استخدم هذه الصفحة لربط كل عطل ظاهر في الحزمة بسببه الجذري المُتحقَّق منه على مستوى المصدر. يوضّح كل مدخل العَرَض والسبب والإصلاح.

Terminal window
composer require nextpdf/laravel
php 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) يُعيد nullnextpdf.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() غير المتدفّقتين إذا كان ترويسة الطول مطلوبة
Terminal window
# Confirm the provider is discovered
php artisan package:discover --ansi
# Inspect merged configuration
php artisan tinker --execute="dump(config('nextpdf.queue'));"
resource: src/Laravel/NextPdfServiceProvider.php (null-check pattern)
<?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/⁩ — لماذا توجد فحوص المسار