Salta ai contenuti

Panoramica dell'integrazione Laravel di NextPDF

Il pacchetto nextpdf/laravel collega il motore PDF di NextPDF a un’applicazione Laravel 12 e registra automaticamente i binding del container. Include una facade Pdf, un helper HTTP PdfResponse e un GeneratePdfJob accodabile. Laravel rileva automaticamente il pacchetto, quindi non occorre registrarlo manualmente.

Terminal window
composer require nextpdf/laravel

Il vincolo Composer è nextpdf/core: ^3.0 || ^5.2. Il pacchetto richiede inoltre laravel/framework: ^12.0 e php: >=8.4 <9.0. Per la procedura completa, compresa la pubblicazione della configurazione e delle estensioni facoltative, vedere /integrations/laravel/install/.

Il pacchetto funge da sottile punto di integrazione tra il service container di Laravel e il core NextPDF indipendente dal framework. Non reimplementa la generazione dei PDF: adatta invece il modello core NextPDF\Core\Document al ciclo di vita, alla configurazione, all’accodamento e ai layer HTTP di Laravel.

Il diagramma seguente mostra come una richiesta passi dal codice dell’applicazione, attraverso il pacchetto, fino ai registry core condivisi.

NextPDF Laravel request and render flowA request resolves a fresh document from the container, which the package adapts onto the shared font and image registries before HTTP or queue output.

Your Laravel app

Pdf facade

Laravel service container

NextPdfServiceProvider (deferred)

DocumentFactory (singleton)

Document (fresh per resolve)

FontRegistry (singleton, locked)

ImageRegistry (singleton, LRU)

PdfResponse (HTTP)

GeneratePdfJob (queue worker)

NextPDF Laravel request and render flow

La mappa di autoload contiene una sola voce PSR-4. PSR-4 è la PHP Standard Recommendation per l’autoloading e il relativo prefisso NextPDF\Laravel\ viene mappato su src/Laravel/. Secondo PSR-4, un prefisso di namespace corrisponde a una directory di base e la parte restante del nome della classe viene quindi mappata su un percorso di file all’interno di quella directory (PSR-4 §3). Sotto questo prefisso si trovano quattro classi di produzione:

  • NextPDF\Laravel\NextPdfServiceProvider — registra i binding e pubblica la configurazione.
  • NextPDF\Laravel\Facades\Pdf — un proxy statico che risolve un documento nuovo dal container.
  • NextPDF\Laravel\Http\PdfResponse — una factory per risposte PDF inline, di download e in streaming con un set fisso di header di sicurezza.
  • NextPDF\Laravel\Jobs\GeneratePdfJob — un job accodabile che genera e salva un PDF su un worker.

Il service provider implementa DeferrableProvider, quindi registra i propri binding solo quando viene risolta una delle voci dichiarate. Questo differimento mantiene leggero il percorso di avvio del framework. Il metodo provides() del provider elenca le voci differite e il container legge questo elenco per rimappare ogni chiave sul provider.

La risoluzione segue il contratto del container: quando un binding è presente, risolvere l’identificatore restituisce la voce registrata. PSR-11 è la PHP Standard Recommendation per l’interoperabilità dei container e specifica che due chiamate get() successive con lo stesso identificatore possono restituire valori diversi, in base alla strategia di binding (PSR-11 §1.1.2). NextPDF si basa intenzionalmente su questo comportamento. I registry sono singleton, quindi ogni risoluzione restituisce la stessa istanza; i documenti sono associati a una factory, quindi ogni risoluzione restituisce una nuova istanza. Per la tabella completa delle durate dei binding, vedere /integrations/laravel/boot-and-discovery/.

L’architettura è pensata per worker a lunga durata, come Octane, RoadRunner e Swoole. Il font registry è un singleton con durata pari al processo: il pacchetto lo precarica una sola volta e poi lo blocca, così nessuna richiesta può modificare lo stato condiviso dei font. L’image registry è un singleton con durata pari al processo e dotato di una cache LRU (least-recently-used) limitata. Poiché il pacchetto crea sempre il documento ex novo da una DocumentFactory, lo stato mutabile della singola richiesta non viene mai trasferito tra richieste diverse.

ClasseEntry point pubblicoRestituisceScopo
NextPdfServiceProviderregister(), boot(), provides()void / arrayBinding del container, pubblicazione della configurazione, elenco delle voci differite
Facades\Pdfproxy statico (addPage(), cell(), save(), …)static / mixedRisolve PdfDocumentInterface a ogni chiamata
Http\PdfResponseinline(), download(), streamInline(), streamDownload()Response / StreamedResponseRisposte HTTP con header OWASP
Jobs\GeneratePdfJobdispatch(), handle(), then(), catch(), failed()PendingDispatch / void / selfGenerazione di PDF in coda

Chiavi del container registrate dal provider:

ChiaveDurataSi risolve in
NextPDF\Contracts\FontRegistryInterface (alias FontRegistry)singleton, bloccatoNextPDF\Typography\FontRegistry
NextPDF\Graphics\ImageRegistrysingleton, con limite LRUImageRegistry
NextPDF\Contracts\DocumentFactoryInterface (alias DocumentFactory)singletonNextPDF\Core\DocumentFactory
Psr\Http\Client\ClientInterfacesingletonSecurityAwareHttpClient che incapsula CurlHttpClient
NextPDF\Security\Timestamp\TsaClientscopedTsaClient oppure null in assenza di un URL TSA
NextPDF\Contracts\SignerInterfacefactoryDigitalSigner oppure null quando la firma è disabilitata
NextPDF\Contracts\PdfDocumentInterface (alias nextpdf)factoryNextPDF\Core\Document
NextPDF\Contracts\EInvoice\{Embedder,Validator,Profile,SchematronRunner}Interfacefactorysi risolve solo quando nextpdf/premium è installato
resource: README.md Quick Start (verified against src/Laravel/Facades/Pdf.php)
<?php
declare(strict_types=1);
use NextPDF\Laravel\Facades\Pdf;
Pdf::addPage();
Pdf::cell(0, 10, 'Hello from Laravel', newLine: true);
Pdf::save(storage_path('app/hello.pdf'));

Per un esempio eseguibile a livello di controller, vedere /integrations/laravel/quickstart/.

Il pattern di produzione risolve il contratto del documento dal container anziché dalla facade, rendendo esplicito e testabile il punto di chiamata. Per il controller completo, con dependency injection (DI) e gestione degli errori, vedere /integrations/laravel/production-usage/.

resource: src/Laravel/Http/PdfResponse.php (download factory)
<?php
declare(strict_types=1);
use NextPDF\Contracts\PdfDocumentInterface;
use NextPDF\Laravel\Http\PdfResponse;
$document = app(PdfDocumentInterface::class);
$document->addPage();
$document->cell(0, 10, 'Invoice', newLine: true);
return PdfResponse::download($document, 'invoice.pdf');
  • Il provider è differito, quindi risolvere una chiave del container non correlata non avvia NextPDF. I binding compaiono solo quando viene richiesta una delle voci di provides().
  • SignerInterface e TsaClient si risolvono in null per progettazione quando la firma o la timestamp authority non sono configurate. Il codice deve verificare se il risultato è null; non dare per scontata l’esistenza di un’istanza.
  • I binding dei contratti e-invoice sono sempre registrati, ma si risolvono in implementazioni concrete Premium disponibili solo quando è installato nextpdf/premium. Risolverli senza Premium genera un errore di classe non trovata, che compare alla prima risoluzione e non all’avvio.
  • La facade restituisce un documento nuovo a ogni risoluzione. Considerare due chiamate statiche Pdf:: nella stessa richiesta, separate da Pdf::clearResolvedInstances(): le due chiamate operano su documenti diversi.

La registrazione del provider viene eseguita in tempo O(1). Il provider associa closure e non costruisce oggetti pesanti, quindi il costo di costruzione è rinviato alla prima risoluzione. Il preriscaldamento del font registry viene eseguito in tempo O(f), dove f è il numero di file di font precaricati, una volta per processo worker. Questa tempistica ammortizza la latenza della prima richiesta nei worker a lunga durata. Il budget di memoria per pagina di questa panoramica è registrato nel campo del front matter performance_budget.

PdfResponse applica un set fisso di header dell’Open Worldwide Application Security Project (OWASP). Gli header sono X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Content-Security-Policy: default-src 'none', X-Robots-Tag e Referrer-Policy: no-referrer. GeneratePdfJob convalida il proprio percorso di output lato worker e questo controllo mitiga payload serializzati manomessi. Per il modello di minaccia completo e la configurazione del deployment, vedere /integrations/laravel/security-and-operations/.

AffermazioneFonteClausolareference_id
Risoluzione del container / semantica della durataPSR-11 Container§1.1.2
Mappatura del prefisso di autoload PSR-4PSR-4 Autoloader§3

Quando è installato nextpdf/premium, lo stesso provider espone funzionalità aggiuntive: firma digitale (PAdES B-B), archiviazione PDF/A e binding dei contratti e-invoice. Il provider le espone tramite le stesse chiavi del container, quindi il pacchetto Core qui documentato non richiede modifiche al codice per adottare queste funzionalità. Per i dettagli, vedere https://nextpdf.dev/get-license/?intent=laravel-signing.

  • /integrations/laravel/install/ — procedura di installazione ed estensioni facoltative
  • /integrations/laravel/quickstart/ — esempio eseguibile di controller
  • /integrations/laravel/configuration/ — ogni chiave di configurazione, verificata rispetto a config/nextpdf.php
  • /integrations/laravel/production-usage/ — controller con DI integrata, gestione degli errori, accodamento
  • /integrations/laravel/boot-and-discovery/ — rilevamento automatico e durate dei binding
  • /integrations/laravel/security-and-operations/ — modello di minaccia e configurazione del deployment