Ga naar inhoud
getnextpdf.com

Eén engine, elk framework

Spec: PSR-11 Container, §1.1.2Spec: PSR-4 Autoloader, §3

De meeste groeiende PHP-landschappen eindigen met meer dan één framework. NextPDF is één PDF-engine die elk ervan op zijn eigen voorwaarden tegemoet treedt: idiomatische bridges voor Laravel, Symfony en CodeIgniter, plus een standalone pad voor code die in geen van alle draait. Het documentmodel is gedeeld. Alleen de manier waarop je het aanroept verandert.

Een aparte PDF-bibliotheek per stack is een stille belasting. Elke bibliotheek heeft zijn eigen eigenaardigheden, zijn eigen lettertypeverwerking, zijn eigen idee van wat geldig betekent. Een factuur die correct rendert vanuit de Laravel-service kan subtiel anders renderen vanuit de Symfony-worker, omdat een andere bibliotheek haar tekende. Nu hangen je archiveringsdoel, je handtekeningplaatsing en je toegankelijkheidstags af van welk team het document heeft uitgeleverd. Het bugrapport zegt “de PDF is verkeerd”, en het antwoord hangt af van welke van de drie engines het produceerde.

Standaardiseren op één engine laat dat oppervlak inklappen. Er is één plek waar een PDF/A-profiel wordt bepaald, één lettertypepijplijn om te certificeren, één validator om te vertrouwen. Het framework waarin je je toevallig bevindt, houdt op een variabele te zijn in de vraag of het document correct is.

  • De kern-engine is framework-agnostisch. nextpdf/core weet niets van HTTP, routing of containerbedrading. Het is een PDF 2.0-engine en niets meer.
  • Elke bridge past aan, hij implementeert niet opnieuw. De Laravel-, Symfony- en CodeIgniter-packages geven je een facade of factory, een HTTP-response-helper, en een gequeued of asynchroon generatiepad — over dezelfde engine.
  • Een bridge volgt je framework, niet je document. Hij verandert hoe je de engine aanroept, nooit wat de engine kan produceren.
  • Standalone is altijd beschikbaar. Een CLI-tool, een daemon of een bibliotheek heeft geen framework om vanaf te bridgen; het construeert een document rechtstreeks.
  • Eén documentmodel reist over alle vier heen. Dezelfde value objects, enums en uitvoercontract verschijnen overal, zodat een document ongewijzigd tussen aanroepplekken beweegt.

De architectuur is een bewuste splitsing. De engine is het bezit; de bridge is een dunne adapter die de idiomen van één framework spreekt. Een bridge registreert een kleine namespace over de gedeelde kern via standaard autoloading (Spec: PSR-4 Autoloader, §3) en geeft een document terug via het containercontract (Spec: PSR-11 Container, §1.1.2). Dat contract is hier de stille held: het laat twee resoluties van dezelfde identifier verschillende instanties teruggeven, en precies zo geeft een bridge je een vers, wegwerpbaar document per request, terwijl het geparste lettertyperegister en de afbeeldingscache procesbrede singletons blijven. Langlevende workers — Octane, RoadRunner, Swoole, Messenger — krijgen geamortiseerd lettertype-parsen zonder state-lek tussen requests, per constructie.

De vier idiomen verschillen alleen aan de oppervlakte:

  1. Core enginenextpdf/core — the framework-agnostic PDF 2.0 engine; the single shared document model, value objects, and output contract.
  2. Laravel bridgenextpdf/laravel — auto-discovered provider, a Pdf facade, a PdfResponse helper, and a queued GeneratePdfJob.
  3. Symfony bridgenextpdf/symfony — an auto-registered bundle, an injectable PdfFactory, a PdfResponse, and an optional Messenger handler.
  4. CodeIgniter bridgenextpdf/codeigniter — a service and pdf() helper, a Pdf library over a disposable Document, and a PdfResponse.
  5. StandaloneNo framework to bridge from — construct a Document directly in a CLI tool, daemon, or library.
One framework-agnostic core engine reached through four idiomatic surfaces: a Laravel facade, an injected Symfony factory, a CodeIgniter service, or a directly constructed standalone document — each handing back the same disposable Document model.

Lees het diagram van links naar rechts en de les is de symmetrie. Elk oppervlak resolvet naar dezelfde Document. De Laravel-facade, de Symfony-factory, de CodeIgniter-service en de standalone-constructor zijn vier deuren naar één kamer.

Dezelfde drie regels intentie, uitgedrukt in elk idioom. Het lichaam dat het document opbouwt — pagina’s, lettertypen, cellen, ondertekenen, conformiteit — is identiek in alle vier, omdat het dezelfde engine is.

<?php
declare(strict_types=1);
// Laravel — resolve a fresh document from the container.
use NextPDF\Contracts\PdfDocumentInterface;
$document = app(PdfDocumentInterface::class);
// Symfony — inject the factory, then ask it for a document.
use NextPDF\Symfony\Service\PdfFactory;
$document = $factory->create(); // PdfFactory injected into your service
// CodeIgniter — pull it from the Services layer.
use NextPDF\CodeIgniter\Config\Services;
$document = Services::pdfDocument();
// Standalone — no framework; construct it directly.
use NextPDF\Core\Document;
$document = Document::createStandalone();
// From here, the code is identical regardless of how $document arrived.
$document->addPage();
$document->cell(0, 10, 'One engine, every framework', newLine: true);
$bytes = $document->getPdfData();

De eerste regels zijn het enige verschil. Alles erna is overdraagbaar: verplaats een documentopbouwende service van Symfony naar een standalone worker en de renderingcode verandert niet, omdat het contract waarop ze steunt niet veranderde.

De veelgemaakte aanname is dat de framework-bridge capaciteiten ontgrendelt — dat langetermijnvalidatie van handtekeningen of gestructureerde e-facturatie arriveert omdat je nextpdf/laravel hebt geïnstalleerd in plaats van de engine rechtstreeks aan te roepen. Dat doet hij niet. Een bridge verandert de aanroepplek, nooit het bereik van de engine. Kerncapaciteiten zoals PDF/A-uitvoer en PAdES-baselineondertekening zijn open source en bereiken elk oppervlak; geavanceerde capaciteiten worden ontgrendeld door een editie en zijn dan via elke bridge of het standalone pad gelijk beschikbaar. Een framework-integratie kiezen is geen featureset kiezen.

Het spiegelmisverstand is dat “één engine” één renderingpad voor elk document moet betekenen. Dat doet het niet. De in-process engine rendert PDF rechtstreeks; wanneer een document echt een browser-grade layout-engine nodig heeft, handelt een renderer-package dat af. Rendering en aanroep zijn aparte assen — de integratiebeslissingsgids is de plek die ze in kaart brengt.

Een bridge breidt niet uit wat de engine kan renderen. Dat is de eerlijke grens, en het is het punt: capaciteit leeft in de kern en de tier, niet in de adapter waarmee je haar bereikt.

Framework bridges over one engine — edition availability
EditionAvailability
Core

Every bridge (Laravel, Symfony, CodeIgniter) and the standalone path are Apache-2.0 and work against Core. They adapt or expose the engine; they do not gate features and do not change what it can produce.

Pro

Advanced capabilities such as long-term signature validation (PAdES B-LT and B-LTA) are unlocked by an edition, then reached identically through any bridge or standalone — never by switching framework. PDF/A archival output and PAdES baseline signing (B-B and B-T) are already in Core, available the same way through every surface.

Enterprise

Structured e-invoicing (EN 16931) and deeper compliance tooling are edition capabilities too, likewise the same whichever surface calls the engine, while conformance validation itself ships in Core.

Twee verdere grenzen verdienen het om duidelijk benoemd te worden. Ten eerste volgt elke bridge een actuele major van zijn framework — Laravel, Symfony en CodeIgniter pinnen elk een ondersteund bereik, dus “elk framework” betekent de ondersteunde versie van elk, niet elke historische release; behandel de eigen documentatie van elk package als gezaghebbend voor zijn API. Ten tweede zijn de bridges framework-adapters, geen rendering-backends. Als een document een volledige browser-layout-engine nodig heeft, is dat een renderer-keuze onafhankelijk van welk framework de engine aanriep.

  • De integratiebeslissingsgids — de use-case-naar-package-kaart, inclusief renderers en het oppervlak van de Connect-service, wanneer je moet beslissen in plaats van standaardiseren.
  • Open core, geen lock-in — waarom de engine het bezit is en de bridges dun zijn, zodat standaardiseren je niet opsluit.
  • De HTML-pijplijn — wat de in-process engine dekt, zodat je weet wanneer een browser-renderer de aparte vraag is.
  • De PHP 8.4-fundamenten — de runtime-bodem die elke bridge en het standalone pad delen.
  • Kern-enginenextpdf/core, de framework-agnostische PDF 2.0-engine waarop elke bridge en het standalone pad bouwen.
  • Framework-bridge — een integratiepackage (Laravel, Symfony, CodeIgniter) dat de engine aanpast aan de idiomen van een framework — facade, factory, response, gequeude job — zonder zijn capaciteiten te veranderen.
  • Standalone pad — de kern-engine rechtstreeks gebruiken, zonder framework, door zelf een Document te construeren; de route voor CLI-tools, daemons en bibliotheken.
  • Wegwerpbaar document — het eenmalig te gebruiken Document-contract: opbouwen, uitstoten, weggooien. Elke containerresolutie geeft een verse terug, zodat er geen state lekt tussen requests in een langlevende worker.
  • PAdES — PDF Advanced Electronic Signatures, de ETSI-profielfamilie voor PDF-ondertekening. Baselineondertekening (B-B en B-T) zit in Core; langetermijnvalidatie (B-LT en B-LTA) is een capaciteit van de geavanceerde editie. Beide worden bereikt via elk oppervlak, uitgebreid behandeld op de ondertekeningspagina’s.