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

العقود / المستند

يضم مجال المستند العقود التي تستخدمها لبناء مخرجات ⁨PDF⁩: PdfDocumentInterface للمحتوى، وDocumentFactoryInterface للإنشاء الآمن داخل العاملين، وعقدَي سجلّي الخطوط والصور، والتعدادات الثلاثة الخاصة بالتسليم والتخطيط. وكلها stable منذ الإصدار 1.0.0 أو 1.7.0.

Terminal window
composer require nextpdf/core:^3

PdfDocumentInterface هو سطح واجهة برمجة التطبيقات (⁨API⁩) الأساسي. ويعرّف إدارة الصفحات، واختيار الخط، وتخطيط نص الخلايا والخلايا المتعددة، وعرض لغة ترميز النص التشعّبي (⁨HTML⁩)، وتضمين الصور، والإخراج النهائي. تُعيد كل دالّة static، بحيث يمكنك تسلسل الاستدعاءات. يُعيد Document::createStandalone() نسخة ملموسة تستوفي الواجهة. استخدم الواجهة في تلميحات الأنواع داخل خدماتك الخاصة كي تبقى الأجزاء الداخلية للمحرّك قابلة للاستبدال.

لإنشاء المستند مساران. في طلب ⁨PHP FastCGI Process Manager⁩ (⁨PHP-FPM⁩) التقليدي، يبني createStandalone() مستندًا قائمًا بذاته بسجلّات خاصة. أما في العاملين طويلي التشغيل، بما في ذلك ⁨RoadRunner⁩ و⁨Swoole⁩ و⁨Laravel Octane⁩، فاستخدم المسار الآخر. هناك، يُعيد DocumentFactoryInterface::create() نسخة Document جديدة قابلة للتخلّص منها. يقرأ المستند من سجلّات تمتد طوال عمر العملية، لكنه لا يُعدّلها أبدًا. يحتفظ المصنع بمفردتَي FontRegistryInterface وImageRegistryInterface (⁨singletons⁩). ويحصل كل مستند على سياق عرض وكاتب خاصّين به. وهذا يحصر الأعطال: فلا يمكن لمستند واحد أن يُفسد حالة مشتركة يعتمد عليها مستند آخر.

تُبقي عقود السجلّ العاملين سريعين. يُحلّل FontRegistryInterface ملف الخط مرة واحدة، ويُخزّن بيانات التعريف المحلّلة مؤقتًا طوال عمر العملية. يمكنك قفله بعد الإحماء كي لا تتمكّن حركة مرور الإنتاج من تعديله. يُخزّن ImageRegistryInterface البيانات الثنائية المفكوكة الترميز للصور مؤقتًا وفق سياسة محدودة للأقل استخدامًا مؤخرًا. وتبقى بيانات تعريف الصورة مقيمة حتى بعد إخلاء البيانات الثنائية. يكشف كلا السجلّين memoryUsage() لأغراض تخطيط السعة. يوسّع ImageRegistryInterface الواجهة ResettableService، التي تُخلي البيانات المخزّنة مؤقتًا دون إتلاف بيانات التعريف البنيوية. يمكن للعامل إسقاط مخازن الصور المؤقتة عند ضغط الذاكرة، ثم متابعة الخدمة.

تُكمل هذا المجال ثلاثة تعدادات. يختار OutputDestination العرض المضمّن، أو فرض التنزيل، أو الكتابة إلى نظام الملفات، أو إعادة سلسلة نصية خام. يختار Orientation الاتجاه الطولي أو العرضي. ويختار Alignment النص المحاذى لليسار، أو المتوسّط، أو المحاذى لليمين، أو المضبوط. يستخدم كل تعداد رمز ⁨TCPDF⁩ القديم قيمةً له، بحيث يتصل جسر compat-tcpdf بسلاسة. ضمان التوافق مع الإصدارات السابقة لهذه التعدادات إضافي: لا تُزال أي حالة، وقد تصل حالات جديدة في إصدار ثانوي.

النوعالصنفالأعضاء الرئيسيةالاستقرارمنذ
PdfDocumentInterfaceواجهةaddPage(), setMargins(), setFont(), cell(), multiCell(), writeHtml(), image(), output(), save()مستقر1.0.0
DocumentFactoryInterfaceواجهةcreate(?Config): Documentمستقر1.7.0
ResettableServiceواجهةreset(): voidمستقر1.7.0
FontRegistryInterfaceواجهةregister(), get(), warmup(), lock(), isLocked(), registerFromBinary(), memoryUsage()مستقر1.7.0
ImageRegistryInterfaceواجهةload(), loadFromString(), getMetadata(), memoryUsage() (⁨extends⁩ ResettableService)مستقر2.0.0
OutputDestinationتعداد (سلسلة نصية)Inline, Download, File, Stringمستقر1.0.0
Orientationتعداد (سلسلة نصية)Portrait, Landscapeمستقر1.0.0
Alignmentتعداد (سلسلة نصية)Left, Center, Right, Justifyمستقر1.0.0

توثّق صفحة الطباعة FontRegistryInterface وImageRegistryInterface بالكامل. وتغطّي هذه الصفحة دورهما في دورة حياة الإنشاء.

examples/01-hello-world.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Hello World');
$doc->addPage();
$doc->setFont('helvetica', '', 24);
$doc->cell(0, 15, 'Hello, NextPDF!', newLine: true);
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 10, 'This is a minimal PDF generated with NextPDF.', newLine: true);
$doc->save(__DIR__ . '/output/01-hello-world.pdf');
examples/02-pdf-factory.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\PdfFactory;
use NextPDF\ValueObjects\{Margin, PageSize};
$factory = PdfFactory::new()
->withPageSize(PageSize::A4())
->withMargins(new Margin(15.0, 15.0, 15.0, 15.0))
->withCompress(true)
->withLang('en');
// The same configured factory creates independent documents.
$doc = $factory->create();
$doc->setTitle('PdfFactory Example');
$doc->setAuthor('NextPDF');
$doc->addPage();
$doc->setFont('helvetica', '', 16);
$doc->cell(0, 12, 'Created via PdfFactory', newLine: true);
$doc2 = $factory->create();
$doc2->addPage();
$doc2->setFont('helvetica', '', 12);
$doc2->cell(0, 10, 'Second document from the same factory.');
$doc->save(__DIR__ . '/output/02-pdf-factory.pdf');

PdfFactory هو الباني غير القابل للتغيير. يُعيد كل استدعاء with*() نسخة جديدة. وفي الخلفية، يُركّب DocumentFactoryInterface، لذلك ينطبق نموذج سجلّ العامل المذكور في النظرة العامة دون توصيل إضافي.

  • يبني createStandalone() سجلّات خاصة. وفي حلقة العامل، يؤدي ذلك إلى إعادة تحليل كل خط في كل طلب. استخدم DocumentFactoryInterface بسجلّات مشتركة بدلًا من ذلك.
  • Document قابل للتخلّص منه بحكم تصميمه. إعادة استخدام نسخة واحدة عبر مستندات منطقية متعددة يُسرّب الحالة. استدعِ create() لكل مستند ودع جامع المهملات يستردّه.
  • يجعل FontRegistryInterface::lock() الدوال register() وaddFontDirectory() وwarmup() تطرح LogicException. اقفله بعد الإحماء، ولا تفعل ذلك أبدًا أثناء معالجة الطلب.
  • يكتب OutputDestination::File إلى نظام ملفات الخادم ويُعيد البايتات الخام. save() هو مسار الحفظ الصريح. لا تخلط بين الاثنين للمستند نفسه.
  • يقبل cell() القيمة bool|string لوسيط الحدود من أجل التوافق مع ⁨TCPDF.⁩ السلسلة النصية الفارغة ليست مماثلة لـ false. مرّر القيمة المُنمّطة التي تقصدها.

تجعل سجلّات الخطوط والصور مجال المستند نظامًا محدودًا بالذاكرة، لا نظامًا يعيد العمل لكل طلب. يهيمن تحليل الخط على الطلب الأول. performance_budget هو 1500 ⁨ms⁩ زمن جدار و64 ⁨MB⁩ ذروة عبر ثلاثة مستندات في مثال العامل. ويكاد تحليل الخط الأول يستهلك كامل تلك الميزانية. بعد الإحماء، يكون العمل المنسوب إلى العقد لكل مستند بترتيب ⁨O⁩(1): بحث في السجلّ وتخصيص سياق. يُعيد memoryUsage() على أي من السجلّين MemoryReport لتخطيط السعة الحية. يحدّ ResettableService::reset() من ذروة الذاكرة تحت الحمل المستمر.

لا تحمل عقود المستند أي سطح تشفيري، لكن ينطبق خطران تشغيليان. أولًا، يقبل image() مسارًا أو محدّد موقع موحّد للموارد (⁨URL⁩). في سيناريوهات المدخلات غير الموثوقة، قيِّد الجلب البعيد عبر ExternalResourcePolicyInterface (راجع صفحة سياسة الأمان) بدلًا من تمرير عناوين ⁨URL⁩ التي يتحكّم بها المستخدم مباشرةً. ثانيًا، writeHtml() هو نقطة الدخول إلى مسار ⁨HTML.⁩ يجب أن تمرّ العلامات غير الموثوقة عبر HtmlSecurityPolicyInterface قبل العرض. لا تعقّم طبقة المستند نفسها. هذه مهمة مجال سياسة الأمان، وبما أنها عقد، يمكنك توفير سياسة أكثر صرامة دون تفريع.

تُنفّذ عقود المستند بنية مستند ⁨PDF 2.0⁩ كما هي معرّفة في ⁨ISO 32000-2.⁩ تُنتج معالجة الإخراج والصفحة والخط كائنات غير مباشرة ودفق مراجع متقاطعة وفق ⁨ISO 32000-2⁩ §7. تُصدر طبقة الكاتب المحتوى وفق عقد طبقة المحرّك وسجلّ قرار المعمارية (⁨ADR-010⁩). لا تؤكّد هذه الصفحة أي ادّعاء على مستوى البند يتجاوز المطابقة البنيوية. توثّق صفحتا الاستخراج وإمكانية الوصول مطابقة ⁨PDF/A⁩ و⁨PDF/UA⁩ وتحملان الجداول المعيارية.