Aller au contenu

NextPDF pour CodeIgniter 4

nextpdf/codeigniter relie le moteur PDF NextPDF à une application CodeIgniter 4 via la couche Services du framework. Tu génères tes documents PDF depuis des contrôleurs, des jobs ou des commandes, puis tu les retournes sous forme de réponses HTTP natives de CodeIgniter.

Fenêtre de terminal
composer require nextpdf/codeigniter

Le fichier composer.json du package exige php >=8.4 <9.0, nextpdf/core ^3.0 || ^5.2 et codeigniter4/framework ^4.6. Il suggère aussi nextpdf/artisan, nextpdf/premium et codeigniter4/queue. Tu trouveras le tableau complet des prérequis, des packages optionnels et des étapes de vérification dans /integrations/codeigniter/install/.

NextPDF est un moteur PDF 2.0 écrit en PHP 8.4. Le moteur central (nextpdf/core) est indépendant de tout framework. Il ne connaît rien au HTTP, au routage ni au câblage des dépendances. nextpdf/codeigniter est l’adaptateur qui relie le moteur à une application CodeIgniter 4. Une fois l’adaptateur en place, tu n’as plus à câbler toi-même les registres, les fabriques ni la gestion des réponses.

Le package ajoute quatre éléments à une application CodeIgniter 4 :

  • Une classe Services (NextPDF\CodeIgniter\Config\Services) que CodeIgniter découvre automatiquement et qui expose des services nommés : fontRegistry, imageRegistry, documentFactory, pdfDocument, pdf, tsaClient et pdfSigner.
  • Une bibliothèque Pdf (NextPDF\CodeIgniter\Libraries\Pdf) — une API de contrôleur de haut niveau. Elle encapsule un document à usage unique et le transforme en réponse en un seul appel.
  • Un assistant PdfResponse (NextPDF\CodeIgniter\Http\PdfResponse) qui produit une DownloadResponse CodeIgniter pour l’affichage en ligne ou le téléchargement. Il attache un ensemble fixe d’en-têtes de durcissement de la réponse.
  • Deux fonctions d’assistance globales, pdf() et pdf_document(). Elles sont enregistrées via l’entrée d’autoload files de Composer et le Registrar du package.

Le package détecte aussi les extensions optionnelles de NextPDF au moment de construire le document. Quand nextpdf/artisan est installé et qu’un binaire Chrome est configuré, le document dispose du renderer Chrome. Quand NextPDF Pro est installé, la sortie PDF/A et la signature numérique deviennent accessibles via la même surface Services. La détection est conditionnelle et silencieuse. Le package n’impose jamais une extension absente.

Pourquoi une classe Services plutôt qu’une liaison de conteneur

Section intitulée « Pourquoi une classe Services plutôt qu’une liaison de conteneur »

CodeIgniter 4 ne fournit pas de conteneur d’injection de dépendances PSR-11. À la place, il s’appuie sur un localisateur Services. Un localisateur Services est une classe avec des méthodes de fabrique statiques, que le framework découvre, où chaque méthode renvoie soit une instance partagée, soit une instance neuve. PSR-11 déconseille explicitement le motif localisateur de services — passer un conteneur à un objet pour que l’objet y récupère lui-même ses dépendances — (PSR-11 §1.3, modal SHOULD NOT). Le package suit la convention de localisateur de CodeIgniter. Il garde aussi la surface du localisateur minimale et explicite : chaque service est une méthode de fabrique nommée avec un paramètre bool $getShared, et les appelants reçoivent des objets concrets plutôt qu’une référence au conteneur.

Cette conception maintient l’intégration CodeIgniter cohérente avec les intégrations Laravel et Symfony. Chacune de ces intégrations expose les mêmes services logiques dans l’idiome propre à son framework.

Point d’entréeTypeRenvoieDurée de vie
Services::fontRegistry()serviceFontRegistryInterfacepartagé (préchauffé, puis verrouillé)
Services::imageRegistry()serviceImageRegistrypartagé (cache LRU borné)
Services::documentFactory()serviceDocumentFactoryInterfacepartagé (sans état)
Services::pdfDocument(false)serviceNextPDF\Core\Documentnouvelle instance à chaque appel
Services::pdf(false)serviceNextPDF\CodeIgniter\Libraries\Pdfnouvelle instance à chaque appel
Services::tsaClient()service?TsaClientpartagé ; null en l’absence d’URL TSA
Services::pdfSigner(false)service?SignerInterfaceneuve ; null quand la signature est désactivée
pdf()assistantPdfnouvelle instance à chaque appel
pdf_document()assistantDocumentnouvelle instance à chaque appel
PdfResponse::inline() / download()statiqueDownloadResponsepar appel
GeneratePdfJobjob de file d’attenteun par dispatch

Un contrôleur renvoie un PDF en trois lignes. Services::pdf() produit une bibliothèque Pdf neuve qui encapsule un document neuf. download() crée ensuite une DownloadResponse 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");
}
}

L’exemple complet et exécutable se trouve dans /integrations/codeigniter/quickstart/. Il couvre le routage, l’affichage en ligne et les variantes des assistants pdf() et pdf_document().

En production, demande une instance non partagée avec Services::pdf(false). Intercepte l’unique exception de base NextPDF\Exception\NextPdfException ; toutes les défaillances du cœur et des extensions en héritent. Journalise la défaillance avec son contexte au lieu de masquer l’erreur.

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]);
}

Le contrôleur de production complet se trouve dans /integrations/codeigniter/production-usage/. Il ajoute la mesure du temps à des fins d’observabilité, des durées de vie sûres pour les workers et la génération asynchrone.

  • Les registres de polices et d’images sont des singletons à durée de vie du processus. Un document n’est jamais partagé. pdfDocument et pdf renvoient une instance neuve à chaque appel, ce qui empêche une requête de laisser fuiter son contenu vers une autre. Services::pdf(false) et pdf() renvoient tous les deux une bibliothèque neuve qui encapsule un document neuf.
  • Le package exige les extensions PHP mbstring et zlib. Le registre de polices le vérifie une fois par processus. Si l’une des deux extensions est absente, le registre de polices lève une erreur d’exécution qui nomme l’extension manquante.
  • Le comportement des extensions optionnelles dépend de ce qui est installé dans la même application. Lorsque seul nextpdf/core est présent, les chemins de signature et de PDF/A renvoient null ou sont ignorés. Ils ne provoquent jamais d’échec bruyant.

L’intégration n’ajoute aucune surcharge mesurable par rapport au moteur lui-même. Le registre de polices est analysé une seule fois, puis verrouillé. Le registre d’images est un cache LRU borné par le réglage imageCacheMb (50 Mo par défaut). Le coût de construction du PDF dépend du moteur central et du contenu du document, pas de l’adaptateur. Le budget par page pour cet ensemble de documentation est de 1500 ms en temps réel / 128 Mo de pic. Les recipes concrètes fixent leur propre budget dans le front-matter.

PdfResponse attache un ensemble fixe d’en-têtes de réponse à chaque PDF qu’il émet : X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Content-Security-Policy: default-src 'none', X-Robots-Tag: noindex, nofollow et Referrer-Policy: no-referrer. Les noms de fichiers sont assainis, et les noms non-ASCII sont envoyés avec un paramètre étendu RFC 5987. Le job de file d’attente restreint les callables de construction au namespace App\PdfBuilders et confine les chemins de sortie à WRITEPATH/pdfs/. Consulte /integrations/codeigniter/security-and-operations/ pour le modèle de menace complet.

  • La découverte des modules repose sur l’autoloading PSR-4 de Composer. Un préfixe de namespace correspond à un répertoire de base, et le nom de classe pleinement qualifié correspond à un chemin de fichier (PSR-4 §x1.x3).
  • La conception des Services suit les recommandations relatives au localisateur évoquées sous PSR-11 §1.3.

Le cœur de NextPDF est sous Apache-2.0. Les signatures numériques, l’archivage PDF/A et l’intégration de factures électroniques Factur-X sont fournis par NextPDF Pro et NextPDF Enterprise. Le package CodeIgniter expose les méthodes de service correspondantes. Ces méthodes renvoient null jusqu’à ce que le package Premium correspondant soit installé dans la même application.

  • /integrations/codeigniter/install/ — installe et vérifie le package.
  • /integrations/codeigniter/quickstart/ — ton premier PDF dans un contrôleur.
  • /integrations/codeigniter/configuration/ — chaque clé de configuration.
  • /integrations/codeigniter/boot-and-discovery/ — comment CodeIgniter trouve la classe Services.
  • /integrations/codeigniter/integration/ — référence de câblage et test de fumée.