Praxistest · Stand: 31. August 2026
TCPDF: PDFs aus PHP — das Gratis-Arbeitstier hinter vier meiner Projekte
Wer eine Webanwendung baut, steht früher oder später vor demselben Wunsch: „Kann ich das als PDF haben?“ — die Zählliste, der Beleg, die Monatsauswertung. Meine Antwort darauf heißt seit Jahren TCPDF: eine kostenlose PHP-Bibliothek (LGPL), die ohne Server-Erweiterungen auskommt und deshalb auf jedem gewöhnlichen Shared Hosting läuft. Bei mir arbeitet sie in vier Projekten: Die Inventur-App druckt damit ihre Zähllisten, die Testkauf-Erfassung ihre Belege, der Haushaltsplaner seine Auswertungen, und ein viertes Werkzeug nutzt sie für Formulare. Grund genug für einen ausführlichen Blick — mit lauffähigem Code und den echten Ergebnissen.
Warum ausgerechnet TCPDF?
Die Bibliothek gibt es seit 2002, sie stammt von Nicola Asuni
und ist laut Packagist über 115 Millionen Mal
installiert worden — ein Urgestein, auf dem halb PHP-Land
aufbaut. Für Hobby-Projekte zählen drei Dinge: Sie kostet nichts,
sie braucht nur PHP (kein ImageMagick, kein Systemwerkzeug), und
sie hat Barcodes eingebaut — EAN, Code 128,
QR-Codes, direkt aus der Kiste. Installation wahlweise per
composer require tecnickcom/tcpdf oder — so mache
ich es auf Shared Hosting — als entpackter Ordner, der per
require eingebunden wird.
Beispiel 1: Vom leeren Blatt zum Brief
Das Grundprinzip: Man erzeugt ein Dokument, wählt Schrift und Ränder und schreibt hinein — gedanklich wie auf ein Blatt Papier, mit Maßen in Millimetern:
<?php
require __DIR__ . '/tcpdf/tcpdf.php';
$pdf = new TCPDF('P', 'mm', 'A4'); // Hochformat, Millimeter, A4
$pdf->setPrintHeader(false); // Standard-Kopf-/Fußzeile aus
$pdf->setPrintFooter(false);
$pdf->SetMargins(25, 25, 20);
$pdf->AddPage();
$pdf->SetFont('helvetica', '', 11);
$pdf->Write(0, "Musterstadt, den 30.08.2026\n\n");
$pdf->SetFont('helvetica', 'B', 14);
$pdf->Write(0, "Betreff: PDF aus vier Zeilen Code\n\n");
$pdf->SetFont('helvetica', '', 11);
$pdf->MultiCell(0, 0,
"Sehr geehrte Leserin, sehr geehrter Leser,\n\n" .
"dieses Dokument entstand ohne Word, ohne Drucker-Dialog und ohne " .
"Cloud-Dienst — nur mit PHP und der kostenlosen Bibliothek TCPDF. " .
"Umlaute wie Ä, Ö, Ü und das ß funktionieren dabei einfach.\n\n" .
"Mit freundlichen Grüßen\nIhr Skript",
0, 'L');
$pdf->Output(__DIR__ . '/brief.pdf', 'F'); // 'F' = als Datei speichern
Der letzte Parameter von Output() ist eine der
nützlichsten Stellschrauben: 'I' zeigt das PDF im
Browser, 'D' erzwingt den Download, 'F'
speichert serverseitig in eine Datei — Letzteres nutze ich für
nächtlich erzeugte Berichte.
Beispiel 2: Die Zählliste — Tabellen aus Zellen
Das Arbeitstier jeder Fachanwendung ist die Tabelle. TCPDF
kann zwar eingeschränkt HTML rendern, aber für sauberes Layout
fahre ich nach Jahren Erfahrung besser mit Cell()
— hier der Tabellen-Kern, aufbauend auf dem Grundgerüst aus
Beispiel 1:
Jede Zelle bekommt Breite, Höhe, Rahmen und Ausrichtung — wie
Lego, nur in Millimetern:
$artikel = [ // je Zeile: [EAN, Artikeltext, Menge, MHD]
['4000140714658', 'Orangina Zero mit Fruchtfleisch', 25, '—'],
['5075331932004', 'Lambrusco', 5, '21.03.2026'],
// …
];
$breiten = [35, 95, 20, 30];
// Kopfzeile mit Hintergrund
$pdf->SetFillColor(240, 240, 240);
$pdf->SetFont('helvetica', 'B', 10);
foreach (['EAN', 'Artikel', 'Menge', 'MHD'] as $i => $titel) {
$pdf->Cell($breiten[$i], 8, $titel, 1, 0, 'L', true);
}
$pdf->Ln();
// Zeilen mit Wechselschattierung, Summe nebenbei
$pdf->SetFont('helvetica', '', 10);
$summe = 0;
foreach ($artikel as $nr => [$ean, $name, $menge, $mhd]) {
$fuellen = $nr % 2 === 1;
$pdf->SetFillColor(250, 250, 250);
$pdf->Cell($breiten[0], 7, $ean, 1, 0, 'L', $fuellen);
$pdf->Cell($breiten[1], 7, $name, 1, 0, 'L', $fuellen);
$pdf->Cell($breiten[2], 7, $menge, 1, 0, 'R', $fuellen);
$pdf->Cell($breiten[3], 7, $mhd, 1, 1, 'L', $fuellen);
$summe += $menge;
}
// Summenzeile
$pdf->SetFont('helvetica', 'B', 10);
$pdf->Cell($breiten[0] + $breiten[1], 8, 'Summe', 1);
$pdf->Cell($breiten[2], 8, $summe, 1, 0, 'R');
$pdf->Cell($breiten[3], 8, '', 1, 1);
Die Denkweise, an die man sich gewöhnen muss: Der fünfte
Parameter von Cell() steuert, ob der Cursor
danach rechts weiterläuft (0) oder eine neue Zeile
beginnt (1). Wer das einmal verinnerlicht hat, baut
Tabellen schneller als in jeder Textverarbeitung.
Beispiel 3: Der Trumpf — Barcodes ohne Zusatzbibliothek
Hier schlägt TCPDF alles, was ich sonst probiert habe: Ein EAN-Strichcode und ein QR-Code sind je ein einziger Methodenaufruf. Für ein Regal-Etikett im eigenen Format reicht das hier:
$pdf = new TCPDF('L', 'mm', [60, 100]); // eigenes Etikettenmaß
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->SetMargins(6, 6, 6);
$pdf->SetAutoPageBreak(false); // wichtig bei Etiketten!
$pdf->AddPage();
$pdf->SetFont('helvetica', 'B', 13);
$pdf->Cell(0, 7, 'Orangina Zero 1,0 l', 0, 1);
$pdf->SetFont('helvetica', '', 22);
$pdf->Cell(0, 11, '1,49 €', 0, 1);
// 1D: EAN-13 mit Klartextzeile darunter
$pdf->write1DBarcode('4000140714658', 'EAN13', 6, 32, 55, 18, 0.4,
['text' => true, 'font' => 'helvetica', 'fontsize' => 8]);
// 2D: QR-Code, z. B. zum Artikel im eigenen System
$pdf->write2DBarcode('https://inventur.vanheek.biz/', 'QRCODE,M', 70, 26, 24, 24);
Ehrliche Praxistipps aus vier Projekten
Schriften mit Bedacht wählen. Die
Kern-Schriften (helvetica, times,
courier) halten PDFs klein. Volle Unicode-Schriften
wie dejavusans können Sonderzeichen aller Sprachen —
blähen die Dateien aber deutlich auf. Für deutsche
Geschäftsdokumente reicht helvetica fast immer.
writeHTML ist eine Abkürzung, kein Browser. TCPDF versteht nur eine Teilmenge von HTML und CSS. Für schnelle Textblöcke gut, für pixelgenaue Tabellen wird es zäh — dann lieber Cells, siehe oben.
Die API zeigt ihr Alter. Hunderte Methoden, gemischte Namenskonventionen, eine Dokumentation, die hauptsächlich aus Beispieldateien besteht. Mein Rat: die offiziellen Beispiele als Steinbruch benutzen — irgendwo dort wurde fast alles schon einmal vorgemacht.
AutoPageBreak kennt keine Gnade. Bei
Etiketten und festen Formaten immer
SetAutoPageBreak(false) setzen, sonst rutscht der
QR-Code auf eine mysteriöse zweite Seite.
Klassiker und Nachfolger
Volle Transparenz zum Projektstatus (Stand 31.08.2026): Das klassische TCPDF ist offiziell im Wartungsmodus — gepflegt wird es trotzdem erstaunlich aktiv, die Versionen 7.0.7 und 6.11.4 erschienen erst vor wenigen Tagen; aktuelle Zweige verlangen PHP 8.2 oder neuer. Die aktive Weiterentwicklung steckt im modularen Nachfolger tc-lib-pdf, den der Autor für neue Projekte empfiehlt — mit vollem UTF-8 samt Rechts-nach-links-Schriften, SVG, digitalen Signaturen und PDF/A. Wichtig zu wissen: Er ist ausdrücklich kein Drop-in-Ersatz, verlangt Composer und eine eigene Font-Generierung. Meine Einordnung: Bestehende Projekte auf dem Klassiker weiterlaufen lassen und aktuell halten; wer heute neu anfängt und mit Composer arbeitet, schaut sich zuerst den Nachfolger an. Und wer die Bibliothek jahrelang gratis einsetzt, darf dem Autor gern eine Spende dalassen — zwei Jahrzehnte Pflege sind kein Selbstläufer.
Fazit
TCPDF ist kein glamouröses Werkzeug — es ist das zuverlässige. Null Euro, null Serveranforderungen, Barcodes inklusive, und nach zwei Jahrzehnten immer noch gepflegt. Alle drei Beispiele wurden für diesen Artikel tatsächlich ausgeführt, und die Bilder sind ungeschönte Renderings genau dieser PDFs (Beispiel 2 zeigt den Tabellen-Kern auf dem Grundgerüst aus Beispiel 1). Wenn deine Webanwendung das nächste Mal gefragt wird, ob es das „auch als PDF“ gibt, lautet die Antwort: ja — mit ein paar Dutzend Zeilen PHP.