Skip to content

compat-legacy quickstart

This page takes you from an installed package to a finished PDF, then to the strict-mode audit you run before migration. Every code block matches behavior asserted by the package test suite, so the output shown here is the output the tests check.

Install the package and confirm the engine link by following /integrations/tcpdf-compat/install/. You need PHP 8.4, and nextpdf/core ^3.0 must be resolved.

Change the import, and keep your TCPDF-style calls. This is the exact surface asserted by tests/Unit/Compat/Tcpdf/TcpdfOutputTest.php.

examples/quickstart-first.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF('P', 'mm', 'A4');
$pdf->SetCreator('Quickstart');
$pdf->SetTitle('First Document');
$pdf->SetFont('helvetica', '', 12);
$pdf->AddPage();
$pdf->Cell(0, 10, 'Hello from the NextPDF engine', 1, 1, 'C');
$pdf->Output(__DIR__ . '/quickstart.pdf', 'F');
echo "Wrote quickstart.pdf\n";

Run it:

Terminal window
php examples/quickstart-first.php

The file quickstart.pdf is valid PDF 2.0. The test suite asserts that the matching string output begins with %PDF for the S, F, and E destinations and for getPDFData().

Output($name, $dest) maps the TCPDF destination codes through a safe output bridge. The test suite exercises this behavior:

$destBehaviorReturns
'S'Return the PDF as a stringPDF bytes (%PDF…)
'F'Write the PDF to the given pathempty string
'E'Return a base64 MIME bodya Content-Type: application/pdf block
'I'Inline (default)per the output bridge
'D'Downloadper the output bridge

Unlike legacy TCPDF, Output() does not echo directly into the active output buffer. You can call it safely inside a queue worker or an HTTP handler that controls its own response. See /integrations/tcpdf-compat/production-usage/.

For a real migration, start by running your existing code with only the import or alias changed. If your codebase calls new \TCPDF(...) against the global namespace, enable the opt-in aliases once at boot (covered in /integrations/tcpdf-compat/boot-and-discovery/):

examples/quickstart-alias.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\LegacyBootstrap;
LegacyBootstrap::enableAliases();
// Legacy code now resolves \TCPDF to the adapter:
$pdf = new \TCPDF('P', 'mm', 'A4');
$pdf->AddPage();
$pdf->SetFont('helvetica', '', 12);
$pdf->Cell(0, 10, 'Legacy call site, modern engine');
$pdf->Output(__DIR__ . '/aliased.pdf', 'F');

LegacyBootstrap::enableAliases() is idempotent. It registers \TCPDF, \TCPDF_STATIC, \TCPDF_FONTS, \TCPDF_COLORS, and \TCPDF_IMAGES only when those classes do not already exist. The package test tests/Unit/Compat/Tcpdf/LegacyBootstrapTest.php asserts that the aliases register, that the call is idempotent, and that new \TCPDF() is an adapter instance. Do not enable aliases if the real TCPDF library is loaded in the same process; see /integrations/tcpdf-compat/troubleshooting/.

This step makes a migration safer. With strict mode off (the default), methods that cannot reproduce TCPDF behavior degrade silently. With strict mode on, they throw TcpdfNotImplementedException with the exact ignored parameters. Run this in a dedicated audit pass, never in production.

examples/quickstart-strict-audit.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\Exception\TcpdfNotImplementedException;
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();
$pdf->setStrictMode(true);
$pdf->AddPage();
$pdf->SetFont('helvetica', '', 12);
try {
// 14 of these parameters are silently ignored by the adapter.
$pdf->Image('photo.jpg', 10, 10, 50, 0, '', '', '', true, 300);
} catch (TcpdfNotImplementedException $e) {
// The message names every ignored parameter and a migration hint.
fwrite(STDERR, $e->getMessage() . "\n");
}

The package test tests/Unit/Compat/Tcpdf/TcpdfStrictModeTest.php asserts that this exact call throws in strict mode and stays silent in default mode, and that the message contains the method name and ignored parameters. Use the collected exceptions as your migration work list — see /integrations/tcpdf-compat/migration/.

Every adapter instance exposes the underlying engine document. Use it to call modern NextPDF methods with no TCPDF equivalent:

examples/quickstart-escape-hatch.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();
$pdf->AddPage();
$pdf->Cell(0, 10, 'Legacy call');
// Drop to the modern engine API:
$document = $pdf->getDocument();
$document->setFont('Helvetica', 'B', 16)
->cell(0, 10, 'Modern fluent API', newLine: true);

getDocument() returns the NextPDF\Core\Document that the adapter wraps. This is the recommended exit path: move your call sites to the modern API one at a time, until you can remove the adapter.

Behavioral differences to expect immediately

Section titled “Behavioral differences to expect immediately”
  • MultiCell() returns 1, not the rendered cell count. Code that branches on the return value of MultiCell() needs adjustment.
  • Error() throws RuntimeException instead of calling die(). Code that relied on process termination must catch the exception.
  • The exact PDF bytes differ from TCPDF output. Re-baseline byte-level test assertions so they check rendered content instead.

The full per-method list is in /integrations/tcpdf-compat/method-coverage/.

  • /integrations/tcpdf-compat/migration/ — the full file-by-file migration strategy.
  • /integrations/tcpdf-compat/configuration/ — strict mode, defaults, and the modern configuration object.
  • /integrations/tcpdf-compat/production-usage/ — workers, output buffers, and performance.
  • /integrations/tcpdf-compat/security-and-operations/ — encryption and signing posture.
  • tests/Unit/Compat/Tcpdf/TcpdfOutputTest.php — output behavior oracle
  • tests/Unit/Compat/Tcpdf/TcpdfStrictModeTest.php — strict-mode oracle
  • docs/TCPDF_COVERAGE.md — authoritative coverage matrix