-
Notifications
You must be signed in to change notification settings - Fork 0
PDF A Conformance
Produce archival-grade PDF files that comply with ISO 19005 (PDF/A-2 or PDF/A-3). Call $doc->enablePdfA() before save() / output() and the library enforces all required constraints, embeds the necessary metadata and colour profile, and generates a file that passes veraPDF validation.
use DragonOfMercy\PhpPdf\Document;
use DragonOfMercy\PhpPdf\Font\Unit;
use DragonOfMercy\PhpPdf\PdfA\PdfALevel;
$doc = new Document(Unit::MM);
$doc->enablePdfA(PdfALevel::A2B);
// All fonts must be embedded - register a custom font family
$doc->registerFontFamily('DejaVu', 'fonts/DejaVuSans.ttf');
$page = $doc->addPage();
$page->setFont('DejaVu', 12);
$page->cell(0, 10, 'Archival document');
$doc->save('archive.pdf');| Case | Standard | Description |
|---|---|---|
PdfALevel::A2B |
ISO 19005-2, level B | Basic: correct visual reproduction. |
PdfALevel::A2U |
ISO 19005-2, level U | Unicode: A-2b plus a valid ToUnicode map on every font (satisfied automatically by custom embedded fonts). |
PdfALevel::A3B |
ISO 19005-3, level B | A-2b plus support for embedded associated files (e.g. Factur-X XML). |
PdfALevel::A3U |
ISO 19005-3, level U | A-2u plus support for embedded associated files. |
-
Forced metadata path. The XMP packet, the
/Infodictionary, and the document/IDpair are always written. Normally/IDand full XMP are optional. -
sRGB output intent. An
[OutputIntent]array is added to the catalog referencing a bundled 588-byte littleCMS sRGB ICC profile (/OutputConditionIdentifier (sRGB IEC61966-2.1)). -
pdfaidXMP schema. Apdfaid:part(2 or 3) andpdfaid:conformance(B or U) block is prepended to the XMP packet.
The PDF version header is already %PDF-1.7, satisfying the PDF/A-2 and PDF/A-3 version requirements.
PDF/A forbids non-embedded fonts. All standard-14 fonts (Helvetica, Times, Courier, etc.) are not embedded and will cause a conformance guard error. Register every font via Document::registerFontFamily() before using it.
$doc->enablePdfA(PdfALevel::A2B);
// Register and use a custom embedded font
$doc->registerFontFamily('OpenSans', 'fonts/OpenSans-Regular.ttf', 'fonts/OpenSans-Bold.ttf');
$page->setFont('OpenSans', 12);PDF/A-2u and A-3u require a valid ToUnicode CMap on every font. Custom embedded fonts already carry /ToUnicode streams produced during subsetting, so the U variant is essentially free.
PdfAConformanceGuard is called by output() before serialization. It throws a PdfException in any of these cases:
| Condition | Error |
|---|---|
| A non-embedded standard font (Helvetica, Times, Courier, etc.) is in use. | Register all fonts with registerFontFamily(). |
| Encryption is configured on the same document. | PDF/A forbids encryption. |
Document JavaScript (addDocumentScript()) is present. |
PDF/A forbids embedded scripts. |
Appended revisions (addSignature(), addDocumentTimestamp(), enableLtv()) are present. |
PDF/A forbids incremental updates of this kind. |
Additionally, calling attachFile() on a document configured for PDF/A-2 (part 2) throws immediately because embedded associated files are only permitted at part 3.
PDF/A-3 allows embedding machine-readable files alongside the human-readable PDF. The most common use case is a Factur-X or ZUGFeRD e-invoice XML.
use DragonOfMercy\PhpPdf\PdfA\AFRelationship;
$doc->enablePdfA(PdfALevel::A3B);
$xml = file_get_contents('factur-x.xml');
$doc->attachFile(
$xml,
'factur-x.xml',
AFRelationship::Data,
'text/xml',
'Factur-X invoice data',
);
$doc->save('invoice-pdfa3.pdf');| Parameter | Type | Default | Description |
|---|---|---|---|
$bytes |
string |
- | Raw file content. |
$name |
string |
- | Filename (used as the key in the /EmbeddedFiles name tree and as /F / /UF). |
$relationship |
AFRelationship |
Data |
Semantic relationship of the file to the document. |
$mime |
string |
'application/octet-stream' |
MIME type of the embedded file. |
$description |
string|null |
null |
Optional human-readable description. |
$modDate |
DateTimeImmutable|null |
now | Modification date. Pass explicitly for deterministic output. |
| Case | PDF name | Typical use |
|---|---|---|
AFRelationship::Source |
Source |
File from which this PDF was generated. |
AFRelationship::Data |
Data |
Machine-readable data represented in the PDF (Factur-X default). |
AFRelationship::Alternative |
Alternative |
Alternative representation of the document content. |
AFRelationship::Supplement |
Supplement |
Supplementary material. |
AFRelationship::Unspecified |
Unspecified |
Relationship not specified. |
Attachments work on documents without enablePdfA() as well; in that case they are plain PDF attachments with no conformance restriction.
The library ships a golden test (tests/Golden/PdfA2ConformanceTest.php) that pipes the rendered output through veraPDF --flavour 2b|2u|3b and asserts isCompliant="true". The test auto-skips when a JRE or the veraPDF CLI jar are absent. Run it with:
cd build/
vendor/bin/phpunit tests/Golden/PdfA2ConformanceTest.phpMIT licensed. Source on GitHub - if phppdf helps you, you can buy me a coffee.