Salta ai contenuti

NextPDF per CodeIgniter 4

nextpdf/codeigniter collega il motore PDF NextPDF a un’applicazione CodeIgniter 4 tramite il livello Services del framework. I documenti PDF possono essere costruiti in controller, job o comandi e poi restituiti come risposte HTTP native di CodeIgniter.

Terminal window
composer require nextpdf/codeigniter

Il file composer.json del pacchetto richiede php >=8.4 <9.0, nextpdf/core ^3.0 || ^5.2 e codeigniter4/framework ^4.6. Inoltre suggerisce nextpdf/artisan, nextpdf/premium e codeigniter4/queue. La tabella completa dei requisiti, l’elenco dei pacchetti facoltativi e i passaggi di verifica sono disponibili in /integrations/codeigniter/install/.

NextPDF è un motore PDF 2.0 in PHP 8.4. Il motore principale (nextpdf/core) è indipendente dal framework. Non conosce HTTP, routing o cablaggio delle dipendenze. nextpdf/codeigniter è l’adattatore che collega il motore a un’applicazione CodeIgniter 4. Usando l’adattatore, non è necessario cablare manualmente registry, factory o gestione delle risposte.

Il pacchetto aggiunge quattro elementi a un’applicazione CodeIgniter 4:

  • Una classe Services (NextPDF\CodeIgniter\Config\Services) che CodeIgniter rileva automaticamente e che espone i servizi denominati: fontRegistry, imageRegistry, documentFactory, pdfDocument, pdf, tsaClient e pdfSigner.
  • Una libreria Pdf (NextPDF\CodeIgniter\Libraries\Pdf): un’API per controller di alto livello. Incapsula un singolo documento monouso e lo trasforma in una risposta con una sola chiamata.
  • Un helper PdfResponse (NextPDF\CodeIgniter\Http\PdfResponse) che produce un DownloadResponse di CodeIgniter per l’anteprima in linea o il download. Aggiunge un insieme fisso di header di hardening per la risposta.
  • Due funzioni helper globali, pdf() e pdf_document(). Sono registrate tramite la voce files dell’autoload di Composer e il Registrar del pacchetto.

Il pacchetto rileva anche le estensioni facoltative di NextPDF al momento della creazione del documento. Quando nextpdf/artisan è installato ed è configurato un binario di Chrome, il documento acquisisce il renderer Chrome. Quando è installato NextPDF Pro, l’output PDF/A e la firma digitale diventano disponibili attraverso la stessa superficie Services. Il rilevamento è condizionale e silenzioso. Il pacchetto non richiede mai un’estensione assente.

Perché una classe Services e non un binding di container

Sezione intitolata “Perché una classe Services e non un binding di container”

CodeIgniter 4 non include un container di dependency injection PSR-11. Usa invece un locator Services. Si tratta di una classe con metodi factory statici, rilevata dal framework, in cui ciascun metodo restituisce un’istanza condivisa oppure una nuova istanza. PSR-11 sconsiglia esplicitamente il pattern service-locator, ossia il passaggio di un container a un oggetto affinché possa recuperare le proprie dipendenze (PSR-11 §1.3, modale SHOULD NOT). Il pacchetto segue la convenzione del locator di CodeIgniter. Mantiene inoltre la superficie del locator minima ed esplicita: ogni servizio è un metodo factory denominato con un parametro bool $getShared e i chiamanti ricevono oggetti concreti anziché un handle del container.

Questa scelta progettuale mantiene l’integrazione CodeIgniter coerente con le integrazioni Laravel e Symfony. Ciascuna integrazione espone gli stessi servizi logici attraverso l’idioma del proprio framework.

Punto di ingressoTipoRestituisceDurata
Services::fontRegistry()servizioFontRegistryInterfacecondiviso (preriscaldato, poi bloccato)
Services::imageRegistry()servizioImageRegistrycondiviso (cache LRU limitata)
Services::documentFactory()servizioDocumentFactoryInterfacecondiviso (stateless)
Services::pdfDocument(false)servizioNextPDF\Core\Documentnuovo a ogni chiamata
Services::pdf(false)servizioNextPDF\CodeIgniter\Libraries\Pdfnuovo a ogni chiamata
Services::tsaClient()servizio?TsaClientcondiviso; null in assenza di URL TSA
Services::pdfSigner(false)servizio?SignerInterfacenuovo; null quando la firma è disabilitata
pdf()helperPdfnuovo a ogni chiamata
pdf_document()helperDocumentnuovo a ogni chiamata
PdfResponse::inline() / download()staticoDownloadResponsea ogni chiamata
GeneratePdfJobjob di codauno per dispatch

Un controller restituisce un PDF in tre righe. Services::pdf() crea una nuova libreria Pdf che incapsula un nuovo documento. download() produce quindi un DownloadResponse di CodeIgniter.

<?php
declare(strict_types=1);
namespace App\Controllers;
use CodeIgniter\HTTP\DownloadResponse;
use NextPDF\CodeIgniter\Config\Services;
final class InvoiceController extends BaseController
{
public function download(int $id): DownloadResponse
{
$pdf = Services::pdf();
$pdf->document()->addPage();
$pdf->document()->cell(0, 10, "Invoice #{$id}");
return $pdf->download("invoice-{$id}.pdf");
}
}

La procedura completa ed eseguibile è disponibile in /integrations/codeigniter/quickstart/. Copre il routing, l’anteprima in linea e le varianti degli helper pdf() e pdf_document().

In produzione, richiedere un’istanza non condivisa con Services::pdf(false). Catturare l’unica eccezione di base NextPDF\Exception\NextPdfException; ogni errore del core e delle estensioni la estende. Registrare l’errore con il relativo contesto anziché ignorarlo silenziosamente.

try {
$pdf = Services::pdf(false);
$pdf->document()->addPage();
$pdf->document()->cell(0, 10, "Invoice #{$id}");
return $pdf->download("invoice-{$id}.pdf");
} catch (NextPdfException $e) {
$logger->error('pdf.invoice.failed', [
'invoice_id' => $id,
'exception' => $e::class,
'message' => $e->getMessage(),
]);
return $this->response
->setStatusCode(ResponseInterface::HTTP_INTERNAL_SERVER_ERROR)
->setJSON(['error' => 'pdf_generation_failed', 'invoice_id' => $id]);
}

Il controller di produzione completo è disponibile in /integrations/codeigniter/production-usage/. Aggiunge misurazioni temporali per l’osservabilità, durate sicure per i worker e la generazione asincrona.

  • I registry di font e immagini sono singleton per la durata del processo. Un documento non viene mai condiviso. pdfDocument e pdf restituiscono una nuova istanza a ogni chiamata, in modo che una richiesta non possa far trapelare contenuti verso un’altra. Services::pdf(false) e pdf() restituiscono entrambi una nuova libreria che incapsula un nuovo documento.
  • Il pacchetto richiede le estensioni PHP mbstring e zlib. Il registry dei font ne verifica la presenza una volta per processo. Se una delle due estensioni è assente, il registry dei font genera un errore di runtime che indica l’estensione mancante.
  • Il comportamento delle estensioni facoltative dipende da ciò che è installato nella stessa applicazione. Con il solo nextpdf/core presente, i percorsi di firma e PDF/A restituiscono null o vengono saltati. Non generano mai errori espliciti.

L’integrazione non aggiunge alcun overhead misurabile oltre a quello del motore stesso. Il registry dei font viene analizzato una sola volta e poi bloccato. Il registry delle immagini è una cache LRU limitata dall’impostazione imageCacheMb (50 MB per impostazione predefinita). Il costo di creazione del PDF dipende dal motore principale e dal contenuto del documento, non dall’adattatore. Il budget per pagina di questo set di documentazione è di 1500 ms di tempo reale / 128 MB di picco. Le ricette per casi reali definiscono il proprio budget nel front-matter.

PdfResponse aggiunge un insieme fisso di header di risposta a ogni PDF che emette: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Content-Security-Policy: default-src 'none', X-Robots-Tag: noindex, nofollow e Referrer-Policy: no-referrer. I nomi dei file vengono sanitizzati e i nomi non ASCII vengono emessi con un parametro esteso RFC 5987. Il job di coda limita i builder callable al namespace App\PdfBuilders e confina i percorsi di output a WRITEPATH/pdfs/. Per il modello di minaccia completo, vedere /integrations/codeigniter/security-and-operations/.

  • Il rilevamento dei moduli si basa sull’autoloading PSR-4 di Composer. Un prefisso di namespace viene mappato a una directory di base e il nome di classe completo viene mappato a un percorso di file (PSR-4 §x1.x3).
  • La progettazione di Services segue le indicazioni sul locator descritte in PSR-11 §1.3.

Il core di NextPDF è distribuito con licenza Apache-2.0. Le firme digitali, l’archiviazione PDF/A e l’incorporamento di fatture elettroniche Factur-X sono forniti da NextPDF Pro e NextPDF Enterprise. Il pacchetto CodeIgniter espone i metodi di servizio corrispondenti. Tali metodi restituiscono null finché il pacchetto Premium corrispondente non viene installato nella stessa applicazione.

  • /integrations/codeigniter/install/ — installazione e verifica del pacchetto.
  • /integrations/codeigniter/quickstart/ — primo PDF in un controller.
  • /integrations/codeigniter/configuration/ — ogni chiave di configurazione.
  • /integrations/codeigniter/boot-and-discovery/ — come CodeIgniter individua la classe Services.
  • /integrations/codeigniter/integration/ — riferimento di cablaggio e smoke test.