compat-legacy im Produktivbetrieb einsetzen
Auf einen Blick
Abschnitt betitelt „Auf einen Blick“Der Adapter lässt sich gefahrlos in HTTP-Handlern, Queue-Workern und langlaufenden Prozessen betreiben. Er ist sicherer als das Legacy-TCPDF 6.2.13, weil die beiden häufigsten Risiken im Produktivbetrieb beseitigt sind: die direkte Ausgabe in den Puffer und die() bei Fehlern. Diese Seite beschreibt, wie Sie ihn korrekt einsetzen.
Voraussetzung: Schließen Sie das Strict-Mode-Audit unter /integrations/tcpdf-compat/migration/ ab und stellen Sie die Anwendung mit deaktiviertem Strict-Mode (off) bereit.
Ausgabeverarbeitung in Workern und Handlern
Abschnitt betitelt „Ausgabeverarbeitung in Workern und Handlern“Das Legacy-TCPDF-Output() schreibt direkt in den aktiven Ausgabepuffer. Dadurch können Antworten in HTTP-Frameworks beschädigt und Queue-Worker lahmgelegt werden. Der Adapter leitet die Ausgabe stattdessen über eine sichere Ziel-Bridge.
Verwenden Sie das Ziel, das zum jeweiligen Aufrufer passt:
| Kontext | Ziel | Warum |
|---|---|---|
| Queue-Worker, der in den Speicher schreibt | Output($path, 'F') | Schreibt die Datei und gibt einen leeren String zurück. Keine Interaktion mit dem Puffer. |
| Erzeugen und anschließend attach/upload | Output($name, 'S') | Gibt die PDF-Bytes zurück; Sie steuern, wohin sie weitergegeben werden. |
| E-Mail-Anhang | Output($name, 'E') | Gibt einen base64-codierten MIME-Body mit Content-Type: application/pdf zurück. |
| HTTP-Antwort, die Sie selbst steuern | Output($name, 'S') | Rufen Sie die Bytes ab und setzen Sie anschließend Ihre eigenen Header und den Body. |
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\Exception\TcpdfNotImplementedException;use NextPDF\Compat\Tcpdf\TCPDF;
/** * Render an invoice in a queue worker. Returns the storage path. * * @throws \RuntimeException on a render failure (Error() throws, not die()). */function renderInvoiceJob(array $invoice, string $storageDir): string{ $pdf = new TCPDF('P', 'mm', 'A4'); $pdf->SetFont('helvetica', '', 12); $pdf->AddPage(); $pdf->Cell(0, 10, 'Invoice ' . $invoice['number'], 0, 1);
$path = $storageDir . '/invoice-' . $invoice['number'] . '.pdf';
try { $pdf->Output($path, 'F'); // writes file, no buffer pollution } catch (TcpdfNotImplementedException $e) { // Only reachable if strict mode is on — it must NOT be in production. throw new \RuntimeException('Adapter strict-mode gap in production: ' . $e->getMessage(), 0, $e); } catch (\RuntimeException $e) { // Error() throws RuntimeException instead of die(). throw new \RuntimeException('PDF render failed: ' . $e->getMessage(), 0, $e); }
return $path;}Verwenden Sie in einem HTTP-Handler vorzugsweise 'S' und setzen Sie die Header selbst:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();$pdf->AddPage();$pdf->SetFont('helvetica', '', 12);$pdf->Cell(0, 10, 'Report');
$bytes = $pdf->Output('report.pdf', 'S');
header('Content-Type: application/pdf');header('Content-Length: ' . strlen($bytes));header('Content-Disposition: inline; filename="report.pdf"');echo $bytes;Fehlerbehandlung
Abschnitt betitelt „Fehlerbehandlung“Error() wirft eine RuntimeException; es ruft niemals die() auf. Das ist mit Abstand die größte betriebliche Änderung gegenüber dem Legacy-TCPDF.
- Umschließen Sie jeden Render-Einstiegspunkt mit
try/catch. - Bilden Sie die Ausnahme auf den Fehlervertrag Ihrer Anwendung ab (HTTP 5xx, fehlgeschlagener Job, Retry, Dead-Letter).
- Gehen Sie nicht davon aus, dass der Prozess bei einem Render-Fehler endet; das tut er nicht.
Wenn Sie einen regelmäßigen Strict-Mode-CI-Job betreiben (empfohlen), ist eine dort auftretende TcpdfNotImplementedException ein echter Befund: Ein Codepfad verlässt sich auf einen nicht unterstützten TCPDF-Parameter. Behandeln Sie ihn als Migrationsarbeitspaket, nicht als instabilen Test.
Lebenszyklus und Ressourcenverwaltung
Abschnitt betitelt „Lebenszyklus und Ressourcenverwaltung“- Das Dokument erzeugt seine PDF-Bytes verzögert erst beim ersten Ausgabeaufruf.
Close()ist optional; ein Aufruf speichert die Bytes im Cache.Open()ist ein gefahrloser No-Op. endPage()hat keine Wirkung; NextPDF verwaltet den Seitenlebenszyklus. Entfernen Sie es aus Hot Loops; es bringt keinen Mehrwert.- Lassen Sie PHP den Adapter zwischen Jobs per Garbage Collection abräumen.
_destroy()setzt die zwischengespeicherten Daten des Adapters zurück; in normalen Worker-Schleifen müssen Sie es jedoch nicht explizit aufrufen. - Erzeugen Sie für jedes Dokument einen frischen Adapter. Verwenden Sie eine Adapter-Instanz in einem langlaufenden Worker nicht für voneinander unabhängige Dokumente wieder; der Dokumentstatus gilt pro Instanz.
Performance-Hinweise
Abschnitt betitelt „Performance-Hinweise“- Der Adapter ist eine dünne Delegationsschicht; die Kosten entstehen in der Engine, nicht im Adapter.
- Definieren Sie Legacy-Konstanten einmalig beim Boot.
LegacyDefaults::register()undLegacyBootstrap::enableAliases()sind beide idempotent und abgesichert, sodass wiederholte Aufrufe günstig sind. Konstanten pro Request zu definieren, ist verschwendete Arbeit. - Bevorzugen Sie
Output(..., 'S')oder'F'gegenüber'I'/'D'in Nicht-Browser-Kontexten. Die Inline-/Download-Pfade erzeugen framework-unabhängige Ausgaben, die Sie in einem Worker normalerweise nicht möchten. - Profilen Sie bei umfangreicher Generierung die Engine, nicht den Adapter. Das Budget pro Seite für den Eigen-Overhead des Adapters ist im Verhältnis zum Rendering gering.
Nebenläufigkeit
Abschnitt betitelt „Nebenläufigkeit“- Jede Adapter-Instanz ist unabhängig und hält ihren eigenen Dokumentstatus. Nebenläufigkeit auf Prozess- oder Worker-Ebene ist sicher, solange jede Arbeitseinheit ihre eigene Adapter-Instanz verwendet.
- Die Idempotenz-Wächter in
LegacyBootstrapundLegacyDefaultsverwenden prozesslokalen statischen Status; sie sind in typischen PHP-per-request/per-worker-Modellen sicher. Sie sind nicht dafür ausgelegt, veränderbaren Status über Threads hinweg zu teilen.
Checkliste vor dem Produktivbetrieb
Abschnitt betitelt „Checkliste vor dem Produktivbetrieb“- Strict-Mode-Audit abgeschlossen; die Produktion läuft mit deaktiviertem Strict-Mode.
- Alle Render-Einstiegspunkte sind mit
try/catchfürRuntimeExceptionumschlossen (kein Verlass aufdie()). - Worker verwenden
Output(..., 'F')oder'S', niemals den Inline-Pfad. - Legacy-Konstanten einmalig beim Boot definiert, vor der ersten Konstruktion.
- Ein regelmäßiger Strict-Mode-CI-Job ist eingerichtet, um Regressionen abzufangen.
- Byte-genaue Test-Assertions sind als neue Baseline festgelegt (siehe /integrations/tcpdf-compat/migration/).
Siehe auch
Abschnitt betitelt „Siehe auch“- /integrations/tcpdf-compat/security-and-operations/ — Verschlüsselung, Signaturstrategie, Härtung
- /integrations/tcpdf-compat/troubleshooting/ — Fehlermuster im Produktivbetrieb und deren Behebung
- /integrations/tcpdf-compat/configuration/ — Strict-Mode und sauberer Umgang mit Konstanten
- /integrations/tcpdf-compat/migration/ — das Audit, das vor dem Produktivbetrieb abgeschlossen sein muss