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

NextPDF لإطار عمل CodeIgniter 4

تربط nextpdf/codeigniter محرّك تنسيق المستندات المحمول (⁨PDF⁩) في ⁨NextPDF⁩ بتطبيق ⁨CodeIgniter 4⁩ عبر طبقة الخدمات في الإطار. أنشئ مستندات ⁨PDF⁩ داخل المتحكِّمات أو المهام أو الأوامر، ثم أعدها كاستجابات ⁨HTTP⁩ أصلية في ⁨CodeIgniter.⁩

Terminal window
composer require nextpdf/codeigniter

يتطلّب ملف composer.json الخاص بالحزمة php >=8.4 <9.0، وnextpdf/core ^3.0 || ^5.2، وcodeigniter4/framework ^4.6. كما يقترح nextpdf/artisan، وnextpdf/premium، وcodeigniter4/queue. للاطّلاع على جدول المتطلّبات الكامل والحزم الاختيارية وخطوات التحقّق، راجع /⁨integrations/codeigniter/install/.⁩

⁨NextPDF⁩ محرّك ⁨PDF 2.0⁩ مبنيّ على ⁨PHP 8.4.⁩ المحرّك الأساسي (nextpdf/core) مستقلّ عن أي إطار عمل؛ فهو لا يعرف شيئًا عن ⁨HTTP⁩ أو التوجيه أو ربط التبعيات. nextpdf/codeigniter هي المهايئ الذي يصل المحرّك بتطبيق ⁨CodeIgniter 4.⁩ وباستخدام هذا المهايئ، لن تحتاج إلى ربط السجلّات أو المصانع أو معالجة الاستجابة يدويًا.

تضيف الحزمة أربعة أشياء إلى تطبيق ⁨CodeIgniter 4⁩:

  • فئة خدمات (NextPDF\CodeIgniter\Config\Services) يكتشفها ⁨CodeIgniter⁩ تلقائيًا. وتوفّر خدمات مسمّاة: fontRegistry، وimageRegistry، وdocumentFactory، وpdfDocument، وpdf، وtsaClient، وpdfSigner.
  • مكتبة Pdf (NextPDF\CodeIgniter\Libraries\Pdf) — واجهة برمجة تطبيقات (⁨API⁩) عالية المستوى للمتحكِّمات. وهي تغلّف مستندًا واحدًا قابلًا للتخلّص منه، وتحوّله إلى استجابة في استدعاء واحد.
  • مساعد PdfResponse (NextPDF\CodeIgniter\Http\PdfResponse) الذي يُنشئ DownloadResponse في ⁨CodeIgniter⁩ للمعاينة المضمّنة أو التنزيل. كما يُرفِق مجموعة ثابتة من ترويسات تقوية الاستجابة.
  • دالّتان مساعدتان عامّتان، pdf() وpdf_document(). وهما مُسجَّلتان عبر مُدخَل التحميل التلقائي files في ⁨Composer⁩ وRegistrar الخاص بالحزمة.

تكتشف الحزمة أيضًا امتدادات ⁨NextPDF⁩ الاختيارية عند بناء المستند. عند تثبيت nextpdf/artisan وتهيئة ثنائي ⁨Chrome⁩، يحصل المستند على عارض ⁨Chrome.⁩ وعند تثبيت ⁨NextPDF Pro⁩، يصبح إخراج ⁨PDF/A⁩ والتوقيع الرقمي متاحَين عبر سطح الخدمات نفسه. الاكتشاف مشروط وصامت، ولا تتطلّب الحزمة أبدًا امتدادًا غير موجود.

لماذا فئة خدمات وليست ربطًا في حاوية

قسم بعنوان «لماذا فئة خدمات وليست ربطًا في حاوية»

لا يأتي ⁨CodeIgniter 4⁩ مزوّدًا بحاوية حقن تبعيات ⁨PSR-11⁩. بل يستخدم بدلًا من ذلك مُحدِّد موقع خدمات. ومُحدِّد موقع الخدمات فئة يكتشفها الإطار وتحتوي على طرق مصنع ساكنة. تُعيد كل طريقة إمّا نسخة مشتركة وإمّا نسخة جديدة. يُثبّط معيار ⁨PSR-11⁩ نمط مُحدِّد موقع الخدمة — أي تمرير حاوية إلى كائن ليجلب الكائن تبعياته بنفسه — في ⁨PSR-11⁩ §1.3 باستخدام الفعل الكيفي ⁨SHOULD NOT.⁩ تتّبع الحزمة اصطلاح مُحدِّد الموقع الخاص بـ ⁨CodeIgniter.⁩ كما تُبقي سطح مُحدِّد الموقع محدودًا وصريحًا: كل خدمة هي طريقة مصنع مسمّاة ذات وسيط bool $getShared، ويتلقّى المستدعون كائنات فعلية بدلًا من مقبض حاوية.

يُبقي هذا التصميم تكامل ⁨CodeIgniter⁩ متّسقًا مع تكاملَي ⁨Laravel⁩ و⁨Symfony.⁩ يتيح كل تكامل الخدمات المنطقية نفسها عبر اصطلاح إطار العمل الخاص به.

نقطة الدخولالنوعالمُعادالعمر
Services::fontRegistry()خدمةFontRegistryInterfaceمشتركة (تُسخَّن، ثم تُقفَل)
Services::imageRegistry()خدمةImageRegistryمشتركة (ذاكرة تخزين مؤقت محدودة من نوع الأقل استخدامًا مؤخّرًا (⁨LRU⁩))
Services::documentFactory()خدمةDocumentFactoryInterfaceمشتركة (عديمة الحالة)
Services::pdfDocument(false)خدمةNextPDF\Core\Documentجديدة في كل استدعاء
Services::pdf(false)خدمةNextPDF\CodeIgniter\Libraries\Pdfجديدة في كل استدعاء
Services::tsaClient()خدمة?TsaClientمشتركة؛ null عند عدم وجود عنوان ⁨URL⁩ لسلطة الطابع الزمني (⁨TSA⁩)
Services::pdfSigner(false)خدمة?SignerInterfaceجديدة؛ null عند تعطيل التوقيع
pdf()مساعدPdfجديدة في كل استدعاء
pdf_document()مساعدDocumentجديدة في كل استدعاء
PdfResponse::inline() / download()ساكنةDownloadResponseفي كل استدعاء
GeneratePdfJobمهمة طابورواحدة لكل إرسال

يعيد المتحكِّم مستند ⁨PDF⁩ في ثلاثة أسطر. يعيد Services::pdf() مكتبة Pdf جديدة تغلّف مستندًا جديدًا. ثم يُنشئ download() كائن DownloadResponse في ⁨CodeIgniter.⁩

<?php
declare(strict_types=1);
namespace App\Controllers;
use CodeIgniter\HTTP\DownloadResponse;
use NextPDF\CodeIgniter\Config\Services;
final class InvoiceController extends BaseController
{
public function download(int $id): DownloadResponse
{
$pdf = Services::pdf();
$pdf->document()->addPage();
$pdf->document()->cell(0, 10, "Invoice #{$id}");
return $pdf->download("invoice-{$id}.pdf");
}
}

تجد الجولة الإرشادية الكاملة القابلة للتشغيل في /⁨integrations/codeigniter/quickstart/.⁩ وهي تغطّي التوجيه والمعاينة المضمّنة وأشكال الدالّتين المساعدتين pdf() وpdf_document().

في الإنتاج، اطلب نسخة غير مشتركة باستخدام Services::pdf(false). التقط الاستثناء الأساسي الوحيد، NextPDF\Exception\NextPdfException؛ فكل إخفاق في المحرّك الأساسي والامتدادات يرث منه. سجّل الإخفاق مع سياقه بدلًا من تجاهل الخطأ.

try {
$pdf = Services::pdf(false);
$pdf->document()->addPage();
$pdf->document()->cell(0, 10, "Invoice #{$id}");
return $pdf->download("invoice-{$id}.pdf");
} catch (NextPdfException $e) {
$logger->error('pdf.invoice.failed', [
'invoice_id' => $id,
'exception' => $e::class,
'message' => $e->getMessage(),
]);
return $this->response
->setStatusCode(ResponseInterface::HTTP_INTERNAL_SERVER_ERROR)
->setJSON(['error' => 'pdf_generation_failed', 'invoice_id' => $id]);
}

تجد المتحكِّم الإنتاجي الكامل في /⁨integrations/codeigniter/production-usage/.⁩ وهو يضيف توقيت قابلية الرصد، وأعمارًا آمنة للعامل، والتوليد غير المتزامن.

  • سجلّا الخطوط والصور مفردان طوال عمر العملية. ولا يُشارَك أي مستند أبدًا. يعيد pdfDocument وpdf نسخة جديدة في كل استدعاء، بحيث لا يمكن لطلب واحد أن يُسرّب محتوى إلى طلب آخر. يعيد Services::pdf(false) وpdf() كلاهما مكتبة جديدة تغلّف مستندًا جديدًا.
  • تتطلّب الحزمة امتدادَي ⁨PHP⁩ mbstring وzlib. ويتحقّق سجلّ الخطوط منهما مرّة واحدة لكل عملية. إذا غاب أي من الامتدادين، يُطلق سجلّ الخطوط خطأ وقت تشغيل يُسمّي الامتداد المفقود.
  • يعتمد سلوك الامتداد الاختياري على ما هو مثبَّت في التطبيق نفسه. بوجود nextpdf/core وحده، تُعيد مسارات التوقيع و⁨PDF/A⁩ قيمة null أو تُتجاوَز. وهي لا تفشل بصخب أبدًا.

لا يضيف التكامل أي حِمل قابل للقياس يتجاوز المحرّك نفسه. يُحلَّل سجلّ الخطوط مرّة واحدة ثم يُقفَل. سجلّ الصور ذاكرة تخزين مؤقت من نوع ⁨LRU⁩ محدودة بإعداد imageCacheMb (50 ⁨MB⁩ افتراضيًا). المحرّك الأساسي ومحتوى المستند هما ما يحدّدان تكلفة بناء ⁨PDF⁩، لا المهايئ. ميزانية كل صفحة في مجموعة التوثيق هذه هي 1500 ⁨ms⁩ زمن جداري / 128 ⁨MB⁩ ذروة. تضبط الوصفات الحقيقية ميزانيتها الخاصة في البيانات الأمامية.

يُرفِق PdfResponse مجموعة ثابتة من ترويسات الاستجابة بكل مستند ⁨PDF⁩ يُصدِره: X-Content-Type-Options: nosniff، وX-Frame-Options: DENY، وContent-Security-Policy: default-src 'none'، وX-Robots-Tag: noindex, nofollow، وReferrer-Policy: no-referrer. تُنقَّى أسماء الملفات، وتُصدَر الأسماء غير المنتمية إلى ⁨ASCII⁩ بوسيط ممتدّ من نوع طلب التعليقات (⁨RFC⁩) 5987. تَقصُر مهمة الطابور الكائنات القابلة للاستدعاء الخاصة بالباني على فضاء الأسماء App\PdfBuilders، وتحصر مسارات الإخراج في WRITEPATH/pdfs/. راجع /⁨integrations/codeigniter/security-and-operations/⁩ للاطّلاع على نموذج التهديد الكامل.

  • يعتمد اكتشاف الوحدة على التحميل التلقائي ⁨PSR-4⁩ في ⁨Composer.⁩ تُطابَق بادئة فضاء الأسماء مع دليل أساس، ويُطابَق الاسم المؤهّل بالكامل للفئة مع مسار ملف (⁨PSR-4⁩ §⁨x1.x3⁩).
  • يتّبع تصميم الخدمات إرشاد مُحدِّد الموقع المطروح ضمن ⁨PSR-11⁩ §1.3.

⁨NextPDF⁩ الأساسي مرخّص بموجب ⁨Apache-2.0.⁩ التواقيع الرقمية، وأرشفة ⁨PDF/A⁩، وتضمين فاتورة ⁨Factur-X⁩ الإلكترونية توفّرها ⁨NextPDF Pro⁩ و⁨NextPDF Enterprise.⁩ تتيح حزمة ⁨CodeIgniter⁩ طرق الخدمة المقابلة. تُعيد تلك الطرق قيمة null إلى أن تُثبَّت حزمة ⁨Premium⁩ المطابقة في التطبيق نفسه.

  • /⁨integrations/codeigniter/install/⁩ — تثبيت الحزمة والتحقّق منها.
  • /⁨integrations/codeigniter/quickstart/⁩ — أول مستند ⁨PDF⁩ في متحكِّم.
  • /⁨integrations/codeigniter/configuration/⁩ — كل مفتاح تهيئة.
  • /⁨integrations/codeigniter/boot-and-discovery/⁩ — كيف يعثر ⁨CodeIgniter⁩ على فئة الخدمات.
  • /⁨integrations/codeigniter/integration/⁩ — مرجع الربط واختبار الدخان.