Démarrage rapide de NextPDF avec Symfony
En un coup d’œil
Section intitulée « En un coup d’œil »Injecte PdfFactory, construis un Document, puis renvoie ce document via PdfResponse. Pour générer un PDF en arrière-plan, expédie un GeneratePdfMessage sur un transport Messenger.
Étape 1 — Générer un PDF dans un contrôleur
Section intitulée « Étape 1 — Générer un PDF dans un contrôleur »Injecte NextPDF\Symfony\Service\PdfFactory. Sa méthode create() renvoie un NextPDF\Core\Document vierge. Les valeurs par défaut configurées sont déjà appliquées pour toi : le créateur, l’auteur et la langue. Renvoie ensuite ce document via NextPDF\Symfony\Http\PdfResponse.
<?php
declare(strict_types=1);
namespace App\Controller;
use NextPDF\Symfony\Http\PdfResponse;use NextPDF\Symfony\Service\PdfFactory;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\Routing\Attribute\Route;
final class InvoiceController{ #[Route('/invoice/{number}', name: 'invoice_pdf')] public function download(PdfFactory $pdf, string $number): Response { $doc = $pdf->create(); $doc->addPage(); $doc->cell(0, 10, "Invoice #{$number}", newLine: true); $doc->cell(0, 10, 'Thank you for your business.');
return PdfResponse::download($doc, "invoice-{$number}.pdf"); }}PdfResponse::download() renvoie une Symfony\Component\HttpFoundation\Response. Elle contient Content-Type: application/pdf, une disposition attachment, un Content-Length, ainsi que les en-têtes de sécurité fixes du bundle. Symfony documente la classe canonique Response et son modèle d’en-têtes (https://symfony.com/doc/current/components/http_foundation.html).
Étape 2 — Afficher un PDF en ligne
Section intitulée « Étape 2 — Afficher un PDF en ligne »Pour laisser le navigateur afficher le PDF plutôt que le télécharger, utilise inline() :
return PdfResponse::inline($doc, 'preview.pdf');La disposition passe à inline. Tous les autres en-têtes restent identiques.
Étape 3 — Diffuser un PDF volumineux
Section intitulée « Étape 3 — Diffuser un PDF volumineux »Pour les documents volumineux, les variantes en flux diffusent le PDF par blocs de 64 Ko. Cela réduit le pic d’utilisation de la mémoire. Elles renvoient une Symfony\Component\HttpFoundation\StreamedResponse et omettent Content-Length.
return PdfResponse::streamDownload($doc, 'annual-report.pdf');streamInline() en est l’équivalent pour l’affichage en ligne. Symfony documente le contrat de rappel de StreamedResponse : un appelable void qui vide la sortie (https://symfony.com/doc/current/components/http_foundation.html).
Étape 4 — Générer un PDF de façon asynchrone
Section intitulée « Étape 4 — Générer un PDF de façon asynchrone »Quand symfony/messenger est installé, tu peux déplacer la génération hors du thread de requête.
4a — Implémenter un builder
Section intitulée « 4a — Implémenter un builder »Implémente NextPDF\Symfony\Message\PdfBuilderInterface. Le handler te fournit un Document neuf et préconfiguré. Il te fournit aussi le contexte sérialisable issu du message.
<?php
declare(strict_types=1);
namespace App\Pdf;
use NextPDF\Core\Document;use NextPDF\Symfony\Message\PdfBuilderInterface;
final class InvoicePdfBuilder implements PdfBuilderInterface{ public function build(Document $document, array $context): Document { $document->addPage(); $document->setFont('dejavusans', '', 12); $document->cell(0, 10, 'Invoice #' . $context['invoice_id']);
return $document; }}4b — Enregistrer le builder dans le locator
Section intitulée « 4b — Enregistrer le builder dans le locator »Le handler résout les builders depuis un service locator PSR-11 indexé par nom de classe. Par conséquent, seuls les builders enregistrés sont accessibles. Ajoute le builder à un locator dans config/services.yaml :
services: App\Pdf\InvoicePdfBuilder: ~
nextpdf.pdf_builder_locator: class: Symfony\Component\DependencyInjection\ServiceLocator arguments: - 'App\Pdf\InvoicePdfBuilder': '@App\Pdf\InvoicePdfBuilder' tags: ['container.service_locator']
NextPDF\Symfony\Message\GeneratePdfHandler: arguments: $builderLocator: '@nextpdf.pdf_builder_locator'Le handler récupère le builder auprès du locator via son identifiant de type class-string. Un identifiant de conteneur PSR-11 est une chaîne qui identifie de manière unique une entrée (PSR-11 §1.1.2).
4c — Expédier le message
Section intitulée « 4c — Expédier le message »Injecte Symfony\Component\Messenger\MessageBusInterface, puis expédie le message :
<?php
declare(strict_types=1);
namespace App\Controller;
use App\Pdf\InvoicePdfBuilder;use NextPDF\Symfony\Message\GeneratePdfMessage;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\Messenger\MessageBusInterface;use Symfony\Component\Routing\Attribute\Route;
final class ReportController{ #[Route('/invoice/{id}/queue', name: 'invoice_queue')] public function queue(MessageBusInterface $bus, int $id): Response { $bus->dispatch(new GeneratePdfMessage( builderClass: InvoicePdfBuilder::class, outputPath: '/var/storage/invoices/' . $id . '.pdf', builderContext: ['invoice_id' => $id], ));
return new Response('PDF generation queued.', 202); }}GeneratePdfMessage est un DTO readonly. Son constructeur rejette les chemins de sortie vides ou qui ne se terminent pas par .pdf, les segments de traversée de chemin, les schémas de wrapper de flux et les octets nuls. Il exige aussi que builderClass soit un nom de classe syntaxiquement valide. Le handler valide de nouveau le chemin de sortie à l’exécution, avant d’écrire. Ainsi, un chemin sûr lors de l’expédition, mais devenu dangereux lors de la consommation, est tout de même rejeté. L’attribut #[AsMessageHandler] et le contrat d’expédition MessageBusInterface suivent le modèle standard de Symfony Messenger (https://symfony.com/doc/current/messenger.html).
4d — Router le message et lancer un worker
Section intitulée « 4d — Router le message et lancer un worker »Dans config/packages/messenger.yaml, route le message vers un transport :
framework: messenger: transports: async: '%env(MESSENGER_TRANSPORT_DSN)%' routing: NextPDF\Symfony\Message\GeneratePdfMessage: asyncPuis lance un worker :
php bin/console messenger:consume asyncVérifier que ça fonctionne
Section intitulée « Vérifier que ça fonctionne »php bin/console debug:container --tag=container.service_locatorphp bin/console messenger:consume async --limit=1 -vvLa première commande confirme que le builder locator est enregistré. La seconde commande consomme un seul message en file d’attente et affiche l’avancement du handler.
Étapes suivantes
Section intitulée « Étapes suivantes »- /integrations/symfony/configuration/ — ajuste les valeurs par défaut, les polices et le service de document.
- /integrations/symfony/production-usage/ — sécurisation du worker et diffusion en flux sous charge.
- /integrations/symfony/troubleshooting/ — problèmes courants au démarrage et à l’exécution.
Conformité
Section intitulée « Conformité »Chaque ligne correspond à une affirmation normative présente sur cette page, associée à un reference_id complet de 64 caractères hexadécimaux issu du corpus SDO sous accès contrôlé. La provenance (manifeste du corpus, transport utilisé pour la récupération) est indiquée dans _sidecars/rag-citations.yaml.
| Spéc | Clause | reference_id | Affirmation |
|---|---|---|---|
| PSR-11 | psr_11_container#1.1.2.p4 | Contrat d’identifiant du conteneur pour has()/get() |
Voir aussi
Section intitulée « Voir aussi »- /integrations/symfony/overview/ — aperçu des fonctionnalités.
- /integrations/symfony/install/ — installation et enregistrement.
- /integrations/symfony/integration/ — référence du câblage de bout en bout.