Choose Your API
phpdftk organizes PDF generation into four levels. Each level removes a category of concerns. You can drop down a level at any time via escape hatches — methods that return the underlying object from the level below.
Level 3: Pdf (cursor-based, auto-layout, headers/footers, themes) | escape hatch: $pdf->doc() — friendly catalog wrappers | escape hatch: $pdf->writer() — full PdfWriter vLevel 2: PdfDoc (annotations, navigation, metadata, attachments, viewer prefs) | escape hatch: $doc->writer() vLevel 1: PdfWriter + Page (spatial drawing, explicit coordinates, fonts, signing, encryption) | escape hatch: $page->contentStream() / $writer->fileWriter() vLevel 0: PdfFileWriter + PdfObject tree (raw PDF spec objects)What each level removes
Section titled “What each level removes”| Transition | Knowledge eliminated |
|---|---|
| Level 0 → Level 1 | Object numbers, xref, trailer, resource naming, PdfReference wiring, content-stream operators |
| Level 1 → Level 2 | Manual Catalog wiring, register() plumbing for annotations / navigation / metadata |
| Level 2 → Level 3 | Coordinates, page breaks, font management, text measurement |
When to pick which level
Section titled “When to pick which level”- Level 3 —
Pdf: documents that are mostly text and images. You think in content, not coordinates. Headers, footers, watermarks, page numbering all work declaratively. - Level 2 —
PdfDoc: explicit page positioning plus one-call wrappers for everything in the PDF catalog — link annotations, outlines, page labels, named destinations, metadata. Use when you want precise layout but don’t want to assemble annotation objects by hand. - Level 1 —
PdfWriter: full byte/resource control — custom TrueType fonts, image embedding with ICC profiles, encryption, signing, conformance profiles (PDF/A, PDF/UA, ZUGFeRD). - Level 0 —
PdfFileWriter: libraries building on phpdftk, or features the higher levels don’t yet expose.
The same PDF, three ways
Section titled “The same PDF, three ways”The three snippets below all produce a Letter-sized page with the same heading. Skim them top to bottom to see how much each level frees you from.
Level 3: Pdf — high-level builder
Section titled “Level 3: Pdf — high-level builder”For documents that are mostly text and images. You think in terms of content, not coordinates:
use Phpdftk\Pdf\Writer\Pdf;
$pdf = new Pdf();$pdf->addHeading('Hello from phpdftk', 1);$pdf->save('hello-high.pdf');📄 View the sample PDF · View the full script on GitHub ↗
What you get: auto page creation, word wrap, font metrics-based text measurement, heading hierarchy (h1–h6), themes, alignment, bold/italic font resolution, headers / footers / watermarks via decorator closures.
What you give up: precise positioning, custom graphics, non-standard fonts (drop to Level 1 for those).
Escape hatches: $pdf->doc() → PdfDoc, $pdf->writer() → PdfWriter.
Level 2: PdfDoc — friendly document API
Section titled “Level 2: PdfDoc — friendly document API”For documents with precise layout that still benefit from one-call wrappers for catalog features (annotations, navigation, metadata):
use Phpdftk\Pdf\Writer\PdfDoc;use Phpdftk\Geometry\Rectangle;
$doc = new PdfDoc();$page = $doc->addPage();
$doc->setTitle('My Document') ->setAuthor('phpdftk');
$doc->addLink($page, new Rectangle(72.0, 700.0, 200.0, 14.0), 'https://example.com/');$doc->save('/out.pdf');What you get: explicit page creation plus friendly builders for link annotations, outlines, page labels, named destinations, document metadata, file attachments (Phase 4), viewer preferences (Phase 4).
Escape hatch: $doc->writer() → PdfWriter.
Level 1: PdfWriter — object model
Section titled “Level 1: PdfWriter — object model”For documents needing custom fonts, encryption, signing, or precise control over resources:
use Phpdftk\Pdf\Core\Font\StandardFont;use Phpdftk\Pdf\Core\Font\Type1Font;use Phpdftk\Pdf\Writer\PdfWriter;
$writer = new PdfWriter();$page = $writer->addPage(612, 792);$font = $writer->addFont(new Type1Font(StandardFont::Helvetica));
$writer->addContentStream($page) ->beginText() ->setFont($font->getResourceName(), 24) ->moveTextPosition(72, 720) ->showText('Hello from phpdftk') ->endText();
$writer->save('hello-mid.pdf');📄 View the sample PDF · View the full script on GitHub ↗
What you get: explicit page creation, font handles (Type1, TrueType, composite, OpenType), content streams with the full PDF operator set, image embedding with ICC profiles, digital signatures, encryption, conformance enforcement.
Escape hatches:
$page->contentStream()— rawContentStreamfor PDF operators$page->corePage()— the underlyingCore\Document\Pagefor resource/annotation access$writer->fileWriter()— thePdfFileWriterfor byte-level control
Level 0: PdfFileWriter — byte-level
Section titled “Level 0: PdfFileWriter — byte-level”For libraries building on top of phpdftk, or when you need something the higher levels don’t expose:
use Phpdftk\Pdf\Core\Content\ContentStream;use Phpdftk\Pdf\Core\Content\Resources;use Phpdftk\Pdf\Core\Document\Catalog;use Phpdftk\Pdf\Core\Document\Page;use Phpdftk\Pdf\Core\Document\PageTree;use Phpdftk\Pdf\Core\File\PdfFileWriter;use Phpdftk\Pdf\Core\PdfArray;use Phpdftk\Pdf\Core\PdfNumber;use Phpdftk\Pdf\Core\PdfReference;
$fw = new PdfFileWriter();$catalog = new Catalog();$fw->setCatalog($catalog);
$pageTree = new PageTree();$fw->register($pageTree);$catalog->pages = new PdfReference($pageTree->objectNumber);
$font = new Type1Font(StandardFont::Helvetica);$fw->register($font);
$page = new Page();$page->mediaBox = new PdfArray([ new PdfNumber(0), new PdfNumber(0), new PdfNumber(612), new PdfNumber(792),]);
$cs = new ContentStream();$cs->beginText()->setFont('F1', 24)->moveTextPosition(72, 720) ->showText('Hello from phpdftk')->endText();$fw->register($cs);
$resources = new Resources();$resources->addFont('F1', new PdfReference($font->objectNumber));$page->contents = [new PdfReference($cs->objectNumber)];$page->resources = $resources;$fw->register($page);
$pageTree->kids = [new PdfReference($page->objectNumber)];$pageTree->count = 1;
file_put_contents('hello-low.pdf', $fw->generate());📄 View the sample PDF · View the full script on GitHub ↗
What you get: total control over every byte in the output. Every PDF spec object is a PHP class with typed properties.
What you give up: convenience. You’re responsible for object numbers, resource dictionaries, page tree wiring, and correct operator sequences.
Migration note (Phase 0)
Section titled “Migration note (Phase 0)”Several methods that used to live on PdfWriter now live on PdfDoc:
setOutline,addOutlineItemsetPageLabelssetNamedDestinationssetInfo,setMetadata,syncInfoToMetadata
They remain on PdfWriter as @deprecated forwarders for one minor release. New code should prefer $pdf->doc()->... (or directly on a PdfDoc instance). See the PdfDoc page for details.