ملف PDF حاوية: الملفات المُضمَّنة والبيانات المرتبطة
Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4Spec: ISO 32000-2, §14.13ISO 32000-2 §14.13Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3
لمحة سريعة
قسم بعنوان «لمحة سريعة»يتصور معظم الناس ملف PDF كومةً من الصفحات. هذا هو الجزء الذي تراه. لكن ملف PDF حاوية أيضاً، ويمكنه حمل ملفات كاملة أخرى بداخله — جدول بيانات، أو حمولة XML، أو المستند المصدري الأصلي — مُحزَّمةً داخل الملف الواحد ذاته الذي تسلّمه إلى شخص آخر.
تشرح هذه الصفحة كيف يعمل ذلك: دفق الملف المُضمَّن الذي يخزّن البايتات، وشجرة الأسماء التي تسردها، والمفتاح الواحد الذي يقرر ما إذا كان المرفق مجرد موجود أم يعني شيئاً فعلاً.
لماذا يهم هذا
قسم بعنوان «لماذا يهم هذا»يبدو المرفق غير المصنَّف والمرفق المصنَّف متطابقين للإنسان. كلاهما ملف يستقلّ داخل ملف PDF، وكلاهما — في هذا المحرك — مرتبط بالمستند. الفرق أن أحدهما يخبر الآلة بالغرض منه، والآخر يترك العلاقة فارغة كي تخمّنها الآلة.
ذلك الفرق هو كل اللعبة في فاتورة إلكترونية هجينة. لا تقرأ منصة الضرائب صفحة فاتورتك؛ بل تقرأ XML الذي ضمَّنته. فإن أُرفِق ذلك الـXML كتلةً غير متمايزة بدلاً من كونه بيانات الفاتورة للمستند المرئي، فلن يكون لدى القارئ المطابق طريقة موثوقة لمعرفة أنه الحمولة الواجب معالجتها. تبدو الصفحة مثالية. فتُرفَض الفاتورة. ويصل الإخفاق بعد أيام، وخلفه دفعة محتجزة.
ضبط العلاقة على نحو صحيح، في الطبقة التي تنتج الملف، أرخص بكثير من اكتشافه فاتورةً مرفوضةً تلو الأخرى.
الخلاصة المختصرة
قسم بعنوان «الخلاصة المختصرة»- يستطيع ملف PDF تضمين بايتات أي ملف بوصفه دفق ملف مُضمَّن (Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4). يحمل الدفق البيانات إضافةً إلى قاموس معاملات صغير: الحجم الأصلي والتواريخ ومجموع تحقق.
- تُفهرَس الملفات المُضمَّنة في شجرة الأسماء
EmbeddedFiles، كي يستطيع القارئ تعدادها بالاسم دون مسح المستند كله. - يمضي الملف المرتبط خطوة أبعد: فيعلن
AFRelationship(Spec: ISO 32000-2, §7.11.3ISO 32000-2 §7.11.3) — واحدة من ثماني قيم معيارية (Source،Data،Alternative،Supplement،EncryptedPayload،FormData،Schema،Unspecified)، أو قيمة مخصَّصة — تذكر كيف يتصل الملف بالمحتوى المرفق به. - تلك العلاقة المصنَّفة هي الآلية وراء الفواتير الإلكترونية الهجينة (ZUGFeRD / Factur-X) ومرفقات PDF/A-3 (Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3).
- يدعم NextPDF بدائيات الحاوية الخام في النواة:
embedFile()وembedFileFromString()بعلاقة صريحة. تضيف الإصدارات المتقدمة مُضمِّن الفواتير الإلكترونية المخصَّص EN 16931 / ZUGFeRD / Factur-X فوق هذه البدائيات.
كيف يتعامل NextPDF مع هذا
قسم بعنوان «كيف يتعامل NextPDF مع هذا»فكّر فيه طبقتين مرصوصتين إحداهما فوق الأخرى.
الطبقة الدنيا هي التخزين. دفق الملف المُضمَّن (Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4) هو بايتات الملف الأصلي ملفوفةً في كائن دفق PDF، مع قاموس معاملات يسجّل الحجم الأصلي وتاريخ التعديل ومجموع تحقق للبيانات غير المضغوطة. يُبلَغ الدفق عبر قاموس مواصفة ملف يشير قاموس /EF فيه إلى دفق الملف المُضمَّن — فالدفق نفسه لا يحمل /EF. يستطيع القارئ سحب الملف خارجاً بايتاً ببايت. ولجعل هذه الملفات قابلة للعثور عليها، يحمل فهرس المستند شجرة أسماء EmbeddedFiles — خريطة مرتَّبة من اسم إلى كل مواصفة ملف — كي يستطيع العارض سرد “إليك الملفات الثلاثة داخل هذا الـPDF” دون السير عبر كل صفحة.
الطبقة العليا هي المعنى. الملف المُضمَّن وحده مجرد موجود. تربط آلية الملفات المرتبطة (Spec: ISO 32000-2, §14.13ISO 32000-2 §14.13) ملفاً بشيء ما — المستند بأكمله، أو صفحة، أو كائن رسومي — وتختمه بـAFRelationship. يعرّف ISO 32000-2 مفردات صغيرة من ثماني قيم معيارية (Spec: ISO 32000-2, §7.11.3ISO 32000-2 §7.11.3)، ويسمح بقيم مخصَّصة أيضاً؛ وتجيب كل قيمة معيارية عن سؤال دقيق:
AFRelationship | ما تؤكده عن الملف |
|---|---|
Source | هذه هي المادة المصدرية التي وُلِّد منها المحتوى المرئي (على سبيل المثال، مستند معالج النصوص الأصلي). |
Data | هذه بيانات منظَّمة مرتبطة بالمحتوى المرئي — والحالة النموذجية هي XML الفاتورة خلف صفحة فاتورة مُعروضة. |
Alternative | هذا تمثيل بديل للمحتوى نفسه (على سبيل المثال، نسخة صوتية أو مرئية). |
Supplement | هذه مادة تكميلية تمدّد المحتوى لكنها ليست جزءاً منه. |
EncryptedPayload | الملف المُضمَّن حمولة مشفَّرة يلفّها PDF كتلةً معتمة. |
FormData | الملف بيانات نموذج (FDF أو XFDF أو حمولة نموذج XML). |
Schema | الملف مخطَّط يصف بنية ملف Data (على سبيل المثال، XSD لبيانات XML أو JSON Schema). |
Unspecified | العلاقة غير مذكورة عمداً. صادقة، لكنها لا تخبر الآلة بشيء. |
وراء هذه الثماني، يسمح المعيار أيضاً بقيم علاقة مخصَّصة خاصة بالتطبيق، فالمفردات قابلة للتوسيع لا ثابتة.
يُعرَّف الملف المرتبط بشيئين يعملان معاً، لا بمفتاح واحد وحده. يقوم الارتباط /AF بـربط مواصفة الملف بجزء من المستند؛ ثم يقوم مفتاح AFRelationship في مواصفة الملف بـذكر العلاقة الدلالية. مدخل /AF على نقطة الارتباط (فهرس المستند، أو صفحة، أو كائن) هو مصفوفة — تحتوي تلك المصفوفة على مواصفة ملف واحدة أو أكثر، عادةً كمراجع غير مباشرة؛ فـ/AF ليس مرجعاً مفرداً. الملف المرتبط على مستوى المستند هو مواصفة الملف المُدرَجة في مصفوفة /AF بفهرس المستند، حاملةً AFRelationship خاصتها. ضع علامة Unspecified على جدول البيانات ذاك، وتكون قد ربطته بالمستند لكنك لم تخبر الآلة بشيء عن السبب. ضع علامة Data على جدول البيانات نفسه، وتكون قد أخبرت كل قارئ مطابق ما هو وما الغرض منه. البايتات هي نفسها. الدلالات ليست كذلك.
ولهذا فإن حالة الفاتورة الإلكترونية ليست “أرفق ملف XML”. بل هي “ضمِّن هذا الـXML بوصفه الملف المرتبط Data لهذا المستند، داخل حامل PDF/A-3 مطابق” — مع بقاء صلاحية الفاتورة والقبول القانوني فحصين منفصلين لا يؤديهما الحامل. للتدفق أربع مراحل، والترتيب هو ما يبقيه صحيحاً.
- Store the bytesThe file is wrapped in an embedded file stream with its size, dates, and a checksum (ISO 32000-2 §7.11.4).
- Register it by nameThe file specification is added to the EmbeddedFiles name tree so a reader can enumerate attachments without scanning the document.
- Declare the relationshipAn AFRelationship value (one of the eight standard values such as Source or Data) marks how the file relates to the content, associated at the document level (ISO 32000-2 §14.13.3).
- Make it archivalA PDF/A-3 carrier permits the embedded payload to ride inside one conforming archival PDF/A document; invoice validity and legal acceptance remain separate checks (ISO 19005-3).
تلك المرحلة الرابعة هي سبب وجود PDF/A-3 ملفاً تعريفياً متميزاً. قيّدت ملفات الأرشفة الأسبق ما يمكن تضمينه؛ أما PDF/A-3 (Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3) فهو الجزء الذي يسمح بأن تستقلّ ملفات من أي تنسيق داخل مستند أرشفة مطابق. إنه يسمح بالحمولة المُضمَّنة — لا يصادق عليها ولا يمنح حالة قانونية. بدونه، لا يمكن للفاتورة الهجينة — ملف واحد هو في آنٍ الصفحة التي يقرؤها شخص والبيانات التي يحلّلها نظام ضريبي — أن تكون مستند أرشفة PDF/A مطابقاً على الإطلاق؛ أما كون الفاتورة صالحة ومقبولة قانونياً فيظل سؤالاً منفصلاً. مُضمِّن الفواتير الإلكترونية المخصَّص الذي تضيفه الإصدارات المتقدمة هو طبقة الراحة فوق هذا تماماً: فهو يضمّن الحمولة، ويضبط العلاقة إلى Data، ويسجّلها على نحو صحيح، كي لا تجمّع سباكة الحاوية يدوياً. تستقر آليات الفوترة والأرشفة الأعمق في الصفحتين المجاورتين المرتبطتين أدناه؛ أما هذه الصفحة فعن الحاوية التي تقومان عليها معاً.
مثال عملي
قسم بعنوان «مثال عملي»برنامج صغير كامل. النداءان المهمان هما الفرق بين ملف مرتبط غير مصنَّف وآخر مصنَّف — والعلاقة وسيطة صريحة ينبغي أن تضبطها. في هذا المحرك، يُنتِج كلا النداءين ملفاً مرتبطاً: فـembedFile() وembedFileFromString() يسجّلان دائماً مواصفة الملف في مصفوفة /AF بفهرس المستند، فالشيء الوحيد الذي تغيّره العلاقة هو ما يعنيه الارتباط. تتخذ العلاقة قيمتها الافتراضية Unspecified، التي تربط الملف لكنها لا تخبر الآلة بشيء عن السبب؛ ولحمولة فاتورة إلكترونية تضبطها إلى Data كي يتمكن القارئ من العثور عليها.
<?php
declare(strict_types=1);
use NextPDF\Core\Document;use NextPDF\Navigation\AFRelationship;
$document = Document::createStandalone();$document->addPage();$document->setFont('helvetica', 'B', 16);$document->cell(0, 12, 'Invoice INV-2026-0042', newLine: true);
// An UNTYPED associated file: the bytes are embedded AND the file spec is// added to the document catalog's /AF array, but the relationship says// nothing about why. A reader can open it; a machine cannot tell its role.// The relationship is left Unspecified (its default); the second argument is// the human-readable description. embedFile accepts the AFRelationship enum.$document->embedFile( '/srv/invoices/INV-2026-0042-source.docx', 'Original source document', AFRelationship::Unspecified,);
// A TYPED associated file: the invoice XML is declared as the DATA behind// the visible page. This is the relationship a hybrid e-invoice reader// looks for — the same intent the dedicated e-invoice embedder sets.// embedFileFromString takes the data, a filename, a description, and a// relationship as a PDF-name string ('/Data').$invoiceXml = $generateCiiXml(); // your ERP authors this; the engine never does$document->embedFileFromString( $invoiceXml, 'factur-x.xml', 'Factur-X invoice data', '/Data',);
$bytes = $document->getPdfData();علاقة '/Data' لا تُخطئ. أما المرفق الأول — المتروك Unspecified — فمرتبط رغم ذلك، لكن من دون معنى مذكور. لأجل كلا النداءين، يكتب المحرك دفق الملف المُضمَّن، ويضيف الملف إلى شجرة الأسماء EmbeddedFiles، ويسرد مواصفة ملفه في مصفوفة /AF بفهرس المستند، ويسجّل العلاقة التي ذكرتها — لا يختار واحدة نيابةً عنك. لا يملك هذا المحرك وضع شجرة-أسماء-فقط: فكل ملف تضمّنه بهذه الطريقة هو ملف مرتبط بالمستند، فالعلاقة هي الرافعة الوحيدة التي تتحكم فيها.
مفهوم خاطئ شائع
قسم بعنوان «مفهوم خاطئ شائع»الافتراض المتكرر هو أن “مُضمَّن” و”مرتبط” كلمتان للشيء نفسه. وهما ليستا كذلك. مُضمَّن عن التخزين — البايتات داخل الـPDF. مرتبط عن الربط — مواصفة الملف مسرودة في مصفوفة /AF على جزء من المستند، وهي تحمل AFRelationship. في نموذج PDF المجرَّد يمكن تضمين ملف في شجرة الأسماء دون أن يُربَط أبداً؛ لكن مسار embedFile() في NextPDF لا يتركه هناك — بل يكتب دائماً الارتباط /AF — لذا فالسؤال المفتوح في هذا المحرك ليس أبداً ما إذا كان ملف مرتبطاً بل ما الذي تذكره العلاقة.
فخ ثانٍ: افتراض أن العارض سيستنتج أي مرفق هو الفاتورة. لا يُفترَض في القارئ المطابق أن يخمّن. بل يبحث عن الملف الذي تذكر علاقته Data. اترك العلاقة Unspecified وتكون قد ربطت الحمولة بينما لم تخبر الآلة بشيء مفيد عن دورها.
الحدود والقيود
قسم بعنوان «الحدود والقيود»آلية الحاوية قوية على نحو يستحق الصدق بشأنه: يقرأ embedFile() أي مسار تستطيع عملية PHP قراءته. هذه هي الميزة — وهي أيضاً الحدّ. يرفق المحرك البايتات التي يُعطاها؛ ولا يقرر، ولا يستطيع أن يقرر نيابةً عنك، ما إذا كان مسار ما هو ما قصدت كشفه.
| Edition | Availability |
|---|---|
| Core | يقرأ |
| Pro | Not in this edition |
| Enterprise | Not in this edition |
حدّان إضافيان يستحقان الذكر صراحةً:
- التضمين ليس تصديقاً. يحمل المحرك البايتات التي تعطيه إياها. أما ما إذا كان XML المُضمَّن حمولة فاتورة مطابقة فسؤال منفصل، يجيب عنه مدقِّق — راجع صفحة الفوترة.
- المرفق المصنَّف ليس وحده ملف أرشفة مطابقاً. جعل الملف الهجين مستند PDF/A-3 قانونياً يتطلب وضع الأرشفة وفحص مطابقة مستقلاً — راجع صفحة الأرشفة.
مستندات ذات صلة
قسم بعنوان «مستندات ذات صلة»- الفواتير والفوترة الإلكترونية — حالة الاستخدام التي تُمكِّنها هذه الآلية: ملف PDF هجين يحمل فاتورة قابلة للقراءة آلياً بوصفها ملفه المرتبط
Data. - الأرشفة وPDF/A — لماذا يكون الحامل ملف PDF/A-3 وما الذي تعد به المطابقة وما لا تعد به.
- تشريح ملف PDF — أين تستقر شجرة الأسماء وفهرس المستند في بنية الملف.
- الأدفاق والمرشِّحات — كيف تُخزَّن بايتات ملف مُضمَّن وتُضغَط داخل كائن دفق.
مسرد المصطلحات
قسم بعنوان «مسرد المصطلحات»- دفق الملف المُضمَّن — كائن دفق PDF يحمل بايتات ملف خارجي، مع قاموس معاملات يسجّل حجمه الأصلي وتواريخه ومجموع تحقق (ISO 32000-2 §7.11.4).
- شجرة الأسماء EmbeddedFiles — الخريطة المرتَّبة في فهرس المستند التي تسرد الملفات المُضمَّنة بالاسم، كي يستطيع القارئ تعداد المرفقات دون مسح المستند كله.
- الملف المرتبط — ملف مُضمَّن مربوط بجزء من المستند بارتباط
/AF(على فهرس المستند، أو صفحة، أو كائن) وحاملاًAFRelationshipتذكر كيف يتصل بذلك المحتوى؛ والحالة على مستوى المستند — مواصفة الملف في مصفوفة/AFبالفهرس — هي ما تتمحور حوله هذه الصفحة (ISO 32000-2 §14.13.3). - AFRelationship — مفتاح مواصفة الملف الذي تسمّي قيمته العلاقة (ISO 32000-2 §7.11.3). يتخذ واحدة من ثماني قيم معيارية (
Source،Data،Alternative،Supplement،EncryptedPayload،FormData،Schema،Unspecified) أو قيمة مخصَّصة؛ وDataهي القيمة التي تستخدمها حمولة فاتورة إلكترونية هجينة. - PDF/A-3 — ملف أرشفة ISO 19005-3 الذي يسمح بتضمين ملفات من أي تنسيق، مُمكِّناً مستنداً هجيناً مطابقاً.
- الفاتورة الهجينة — ملف PDF واحد هو في آنٍ صفحة قابلة للقراءة بشرياً وحمولة فاتورة مُضمَّنة قابلة للقراءة آلياً.