Skip to content

NextPDF compat-legacy boot and discovery

nextpdf/compat-legacy exposes NextPDF\Compat\Tcpdf\TCPDF, a TCPDF-compatible facade that delegates to the NextPDF engine. It is a compatibility layer, not a drop-in clone. It directly delegates 94 of the roughly 120 surveyed TCPDF 6.x methods. The remaining methods have documented behavioral differences; see /integrations/tcpdf-compat/method-coverage/.

There is no autoload-time global wiring. Requiring the package does not create a global \TCPDF class by default. You opt in to global aliases explicitly, or, preferably during migration, import the adapter class per file.

The facade is a standard PHP Standard Recommendation 4 (PSR-4) autoloaded class:

ItemValue
Facade classNextPDF\Compat\Tcpdf\TCPDF
PSR-4 prefixNextPDF\Compat\Tcpdf\ maps to src/Compat/Tcpdf/
Shared contractNextPDF\Compat\Contracts\CompatAdapterInterface
Escape hatchTCPDF::getDocument() returns the wrapped NextPDF\Core\Document

The class is intentionally not final. Legacy TCPDF users often subclass TCPDF to override Header() and Footer(), and the adapter preserves that extension point. Internally, the class acts as a facade. It composes 25 single-responsibility concern traits and delegates all Portable Document Format (PDF) operations to a Document instance created when the facade is built.

Composer autoload

Class referenced: new TCPDF or new global TCPDF

Constructor runs

LegacyDefaults::register defines K_/PDF_ constants if absent

ConstructorBridge::build maps orientation/unit/format to Document

Document, UnitConverter, PageSize stored on the facade

Creator/Author seeded from PDF_CREATOR / PDF_AUTHOR

Diagram

Construction is the only “boot” step. The package itself registers no service container and performs no framework bootstrapping. You add framework integration as a thin layer; see /integrations/tcpdf-compat/integration/.

LegacyDefaults::register() is idempotent: it defines a constant only when that constant is not already defined. Application-defined constants always win if you define them before the first construction; see /integrations/tcpdf-compat/configuration/ § Configuration resolution order.

If your codebase calls new \TCPDF(...) in the global namespace and you cannot change those call sites yet, register global aliases once during application boot:

examples/boot-aliases.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\LegacyBootstrap;
LegacyBootstrap::enableAliases();
// Global names now resolve to the adapter:
$pdf = new \TCPDF('P', 'mm', 'A4');

enableAliases() registers \TCPDF, \TCPDF_STATIC, \TCPDF_FONTS, \TCPDF_COLORS, and \TCPDF_IMAGES. tests/Unit/Compat/Tcpdf/LegacyBootstrapTest.php asserts this behavior:

  • It is idempotent: calling it twice does not throw and registers once.
  • LegacyBootstrap::isRegistered() reports whether it has run.
  • After registration, new \TCPDF() creates an instance of the adapter.

Conflict avoidance with a real TCPDF install

Section titled “Conflict avoidance with a real TCPDF install”

This is the single most important rule on this page.

enableAliases() registers an alias only if no class with that name already exists (class_exists($alias, autoload: false)). Therefore:

  • If tecnickcom/tcpdf is installed and its \TCPDF loads first, the alias is silently skipped, and your code keeps using legacy TCPDF, not the adapter.
  • Running both libraries with global aliases enabled in the same process is unsupported and produces ambiguous behavior.

During migration, prefer explicit per-file imports (use NextPDF\Compat\Tcpdf\TCPDF;). They are easy to search and unambiguous. Remove tecnickcom/tcpdf once the strict-mode audit passes; see /integrations/tcpdf-compat/migration/ Stage 5. When \TCPDF resolves to the wrong class, /integrations/tcpdf-compat/troubleshooting/ has the diagnostic.

The package does not ship framework container bindings. If you bind the facade in a container, bind a factory that returns a fresh NextPDF\Compat\Tcpdf\TCPDF for each document. Document state is per-instance and must not be shared across unrelated documents; see /integrations/tcpdf-compat/production-usage/ § Concurrency. /integrations/tcpdf-compat/integration/ shows a typical binding.

At construction, the adapter resolves configuration in this order: constructor arguments first, then any existing application-defined legacy constants, and then the LegacyDefaults TCPDF 6.2.13 defaults for any constant that is not already defined. For full detail and the modern AdaptationConfig object, see /integrations/tcpdf-compat/configuration/.

To confirm the facade is wired and the engine link resolves, construct an adapter, produce a one-page PDF, and check the %PDF prefix. The package output tests assert the same surface. The runnable check is in /integrations/tcpdf-compat/install/ § Verify the installation.

To detect a real-TCPDF conflict before you enable aliases, check whether a global \TCPDF already exists where you would call enableAliases(). If it does, the alias will be skipped. Resolve the conflict with explicit imports, or remove the real TCPDF before you rely on the adapter.

The authoritative, test-verified coverage matrix is the in-repo file docs/TCPDF_COVERAGE.md. The reader-facing summary, including the silent-ignore and unimplemented method lists, is /integrations/tcpdf-compat/method-coverage/. This package does not claim to be a “drop-in replacement” or “100% TCPDF compatible”; it is a TCPDF-compatible alternative with a known, tested compatibility surface and documented behavioral differences.

  • docs/TCPDF_COVERAGE.md — authoritative coverage source (in-repo)
  • /integrations/tcpdf-compat/integration/ — wiring the facade into an application/framework
  • /integrations/tcpdf-compat/method-coverage/ — per-method behavior and gaps
  • /integrations/tcpdf-compat/migration/ — staged migration strategy
  • /integrations/tcpdf-compat/troubleshooting/ — alias/real-TCPDF conflict diagnosis
  • tests/Unit/Compat/Tcpdf/LegacyBootstrapTest.php — alias behavior oracle