Writer: serializer PDF 2.0 + xref
Sekilas pandang
Bagian berjudul “Sekilas pandang”Modul Writer melakukan serialisasi dokumen menjadi byte Portable Document Format (PDF). Modul ini memilih strategi versi, menulis graf objek, lalu menghasilkan struktur referensi silang dan trailer.
Instalasi
Bagian berjudul “Instalasi”composer require nextpdf/core:^3Gambaran konseptual
Bagian berjudul “Gambaran konseptual”Gunakan PdfWriter sebagai titik masuk. Berikan objek nilai DocumentData ke write(). Metode ini mengembalikan PDF lengkap dalam bentuk string byte. Writer merakit graf objek, menetapkan nomor objek, mencatat offset byte, lalu menulis struktur referensi silang paling akhir.
Pada setiap pemanggilan, writer menggunakan satu strategi serialisasi. Antarmuka PdfSerializationStrategy mendefinisikan empat metode: writeHeader(), getCatalogVersion(), writeXrefAndTrailer(), dan usesXrefStream(). Tiga strategi mengimplementasikan antarmuka ini. Pdf20StreamStrategy menulis header %PDF-2.0, menetapkan versi katalog sebagai /2.0, lalu menghasilkan aliran referensi silang. Pdf17TableStrategy menulis %PDF-1.7 dan tabel referensi silang klasik. Pdf14TableStrategy menulis %PDF-1.4 dan tabel referensi silang. PdfWriter memilih strategi melalui match pada DocumentData::$outputProfile. Secara default, strategi yang digunakan adalah Pdf20StreamStrategy.
Enum PdfOutputProfile memuat tiga versi target: Pdf20, Pdf17, dan Pdf14. Enum ini mengekspos headerVersion(), catalogVersion(), allowsObjectStreams(), dan usesXrefStream(). Mode kesesuaian arsip mengesampingkan profil yang dipilih sebelum strategi ditentukan. Pdf14FeatureGuard menolak fitur PDF 2.0 ketika profilnya Pdf14.
Aliran referensi silang memetakan setiap nomor objek ke offset byte-nya, sebagaimana didefinisikan oleh ISO 32000-2 §7. Pembaruan inkremental menambahkan objek baru ke akhir berkas, sebagaimana didefinisikan oleh ISO 32000-2 §7.5.6. Writer melakukan escaping pada setiap string literal melalui jalur kanonis PdfStringEscaper::escapeLiteral(), yang mengikuti tabel escape normatif dalam ISO 32000-2 §7.3.4.2 (ADR-015).
Writer mendukung keluaran deterministik. setDeterministicMode() mengunci pengidentifikasi objek dan urutan kunci kamus. setReproducibleClock() mengunci stempel waktu dokumen. Dengan kedua penguncian tersebut disetel, masukan yang sama menghasilkan keluaran yang identik secara byte. Metode writeChunked() mengembalikan generator yang menghasilkan PDF dalam potongan berukuran tetap. Streaming/StreamingPdfWriter menulis halaman satu per satu ke stream yang disediakan pemanggil untuk dokumen yang melampaui anggaran memori.
Linearizer menulis ulang PDF yang telah selesai menjadi tata letak terlinearisasi. Linearizer menempatkan halaman pertama di awal, sehingga penampil dapat menampilkannya sebelum pengunduhan penuh selesai. shadowValidate() memeriksa hasil penulisan ulang tanpa mengubah masukan.
Perhatian.
PdfWriter.phpdanLinearizer.phpsangat penting bagi offset byte dan graf objek (zona bahaya yang tercatat dalam manifest). Jangan mengubah penomoran objek atau aritmetika offset xref tanpa menjalankan golden suite Writer.
Permukaan API
Bagian berjudul “Permukaan API”| Kelas | Metode utama | Peran |
|---|---|---|
PdfWriter | write(DocumentData): string, writeChunked(DocumentData, int): Generator, setDeterministicMode(), setReproducibleClock(), setOutputColorProfile(), getLastXrefOffset(), getFileId() | Serializer utama |
PdfSerializationStrategy (antarmuka) | writeHeader(), getCatalogVersion(), writeXrefAndTrailer(), usesXrefStream() | Kontrak strategi versi |
Pdf20StreamStrategy | writeHeader() → %PDF-2.0, getCatalogVersion() → /2.0, usesXrefStream() → true | Strategi xref-stream PDF 2.0 |
Pdf17TableStrategy | writeHeader() → %PDF-1.7, tabel xref | Strategi xref-table PDF 1.7 |
Pdf14TableStrategy | writeHeader() → %PDF-1.4, tabel xref | Strategi xref-table PDF 1.4 |
PdfOutputProfile (enum) | Pdf20, Pdf17, Pdf14; headerVersion(), catalogVersion(), allowsObjectStreams() | Pemilih versi target |
PdfXrefWriter | generateFileId(), finalizeTrailerAndXref() | Finalisasi File ID + trailer/xref |
Linearizer | linearize(string): string, shadowValidate(string): array | Penulisan ulang fast-web-view |
Streaming\StreamingPdfWriter | open(), newPage(), close() | Writer streaming satu lintasan |
Jalankan composer docs:generate-api-php -- --module=Writer untuk menghasilkan tabel PHPDoc yang lengkap.
Contoh kode — Mulai cepat
Bagian berjudul “Contoh kode — Mulai cepat”Sumber: examples/02-pdf-factory.php.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Writer\PdfWriter;
$writer = new PdfWriter();$pdfBytes = $writer->write($documentData);
file_put_contents('out.pdf', $pdfBytes);Secara default, profilnya adalah PDF 2.0. Keluaran dimulai dengan %PDF-2.0 dan diakhiri dengan aliran referensi silang.
Contoh kode — Produksi
Bagian berjudul “Contoh kode — Produksi”Contoh ini mengunci mode deterministik dan jam tetap untuk keluaran yang identik secara byte, lalu melakukan streaming hasilnya dalam potongan berukuran tetap.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use DateTimeImmutable;use NextPDF\Writer\PdfWriter;use NextPDF\Writer\ReproducibleClock;
$pinned = new DateTimeImmutable('2026-01-01T00:00:00Z');
$writer = new PdfWriter();$writer->setDeterministicMode($pinned, 'nextpdf-fixed-file-id');$writer->setReproducibleClock(new ReproducibleClock($pinned));
$out = fopen('php://output', 'wb');foreach ($writer->writeChunked($documentData, chunkSize: 65536) as $chunk) { fwrite($out, $chunk);}fclose($out);Kasus tepi & jebakan
Bagian berjudul “Kasus tepi & jebakan”- Hanya satu strategi yang berjalan untuk setiap pemanggilan
write(). Writer mengatur ulang strategi dari profil pada setiap pemanggilan. Versi dari pemanggilan sebelumnya tidak bocor ke pemanggilan berikutnya. - Mode kesesuaian arsip mengesampingkan profil yang diminta. Build PDF/A-3 memaksa PDF 1.7. Build PDF/A-4 memaksa PDF 2.0.
- Keluaran yang identik secara byte memerlukan kedua penguncian. Setel mode deterministik dan jam yang dapat direproduksi. Satu penguncian saja tidak cukup.
writeChunked()menghasilkan generator. Konsumsi generator itu sepenuhnya. Pembacaan sebagian menghasilkan PDF yang terpotong dan tidak valid.Linearizermenulis ulang offset referensi silang. Untuk pipeline yang tidak dapat menoleransi penulisan ulang yang gagal, jalankanshadowValidate()terlebih dahulu.Pdf14TableStrategybersifatfinal readonly. Jalur PDF 1.4 menolak fitur PDF 2.0 melaluiPdf14FeatureGuard; jalur ini tidak melakukan downgrade secara diam-diam.
Kinerja
Bagian berjudul “Kinerja”Serialisasi bersifat linear terhadap jumlah objek dan total ukuran byte. Aliran referensi silang menambahkan satu lintasan pada tabel objek. writeChunked() menahan dokumen yang telah dirakit, tetapi menghasilkannya dalam potongan terbatas, sehingga memori puncak adalah ukuran dokumen ditambah satu potongan. Streaming\StreamingPdfWriter tidak menahan keseluruhan dokumen; gunakan untuk masukan yang lebih besar daripada anggaran memori. Anggaran beban kerja referensi adalah 1500 ms wall dan 64 MB puncak. Linearisasi menambahkan lintasan penuh kedua dan satu lintasan pengukuran. Anggarkan hal itu secara eksplisit.
Catatan keamanan
Bagian berjudul “Catatan keamanan”Writer melakukan serialisasi graf objek tepercaya yang berada di memori. Batas ancaman utamanya adalah masukan. Setiap string literal melewati PdfStringEscaper::escapeLiteral() kanonis (ADR-015), sehingga byte kontrol yang tertanam tidak dapat keluar dari token string. Enkripsi diintegrasikan melalui PdfEncryptionWriter dan entri trailer /Encrypt. Enkripsi kunci publik ditolak dengan eksepsi eksplisit, bukan diturunkan secara diam-diam. Mode deterministik dan jam yang dapat direproduksi menghilangkan saluran samping dari stempel waktu dan pengurutan pada keluaran. Lihat /modules/core/security/ untuk model ancaman dokumen dan batas kepercayaan enkripsi.
Kesesuaian
Bagian berjudul “Kesesuaian”Writer menghasilkan struktur berkas PDF 2.0: header %PDF-2.0, versi katalog /2.0, aliran referensi silang, dan escaping string literal sesuai tabel escape ISO 32000-2 §7.3.4.2. Ini adalah fakta implementasi. Buktinya tersedia di src/Writer/Pdf20StreamStrategy.php, src/Writer/PdfSerializationStrategy.php, dan pemilihan strategi di src/Writer/PdfWriter.php. Perilaku ini diuji oleh tests/Unit/Writer/ (192 tes, termasuk suite Pdf20StreamStrategy, PdfXrefWriter, dan Linearizer*) serta baseline tests/Golden/PdfWriter/PdfWriterGoldenBaselineSmokeTest.
Ini bukan klaim kesesuaian PDF 2.0 penuh. Kesesuaian ISO 32000-2 penuh adalah properti dokumen lengkap yang divalidasi oleh oracle eksternal, bukan properti serializer saja. Kesesuaian menyeluruh hanya ditegaskan ketika oracle mengonfirmasinya: tests/Integration/Accessibility/VeraPdfUa2GoldenTest memvalidasi fixture yang dihasilkan terhadap veraPDF untuk PDF/UA-2, dan tests/Standards/Profile/PdfRConformanceTest mencakup profil PDF/R. Tes golden veraPDF dilewati ketika biner veraPDF tidak tersedia pada runner, sehingga ini adalah gerbang oracle yang bersifat opt-in, bukan gerbang tanpa syarat. Setel VERAPDF_BINARY untuk menjalankannya. Pemilihan profil arsip (PDF/A-3 → PDF 1.7, PDF/A-4 → PDF 2.0) ditentukan oleh ADR-011 dan mode kesesuaian, serta divalidasi oleh suite kesesuaian di /modules/core/conformance/. Untuk profil di luar dukungan oracle tersebut, nyatakan bahwa Writer “menghasilkan struktur PDF 2.0; kesesuaian divalidasi oleh veraPDF untuk profil PDF/UA-2” daripada menegaskan kesesuaian tanpa kualifikasi.