Ga naar inhoud

NextPDF Symfony-snelstart

Injecteer PdfFactory, bouw een Document en retourneer het via PdfResponse. Als je generatie op de achtergrond nodig hebt, stuur je een GeneratePdfMessage naar een Messenger-transport.

Stap 1 — Een PDF genereren in een controller

Sectie met titel “Stap 1 — Een PDF genereren in een controller”

Injecteer NextPDF\Symfony\Service\PdfFactory. De methode create() retourneert een nieuw NextPDF\Core\Document. Daarbij worden je geconfigureerde standaardwaarden toegepast voor de creator, de auteur en de taal. Retourneer het document via NextPDF\Symfony\Http\PdfResponse.

src/Controller/InvoiceController.php
<?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() retourneert een Symfony\Component\HttpFoundation\Response. Deze stelt Content-Type: application/pdf, een attachment-dispositie, Content-Length en de vaste beveiligingsheaders van de bundle in. Symfony documenteert de standaardklasse Response en het bijbehorende headermodel (https://symfony.com/doc/current/components/http_foundation.html).

Gebruik inline() wanneer je wilt dat de browser de PDF toont in plaats van deze te downloaden:

return PdfResponse::inline($doc, 'preview.pdf');

De dispositie verandert in inline. Alle andere headers blijven gelijk.

Gebruik de gestreamde varianten voor grote documenten. Ze verzenden de PDF in blokken van 64 KB, waardoor het piekgeheugengebruik daalt. Ze retourneren een Symfony\Component\HttpFoundation\StreamedResponse en laten Content-Length weg.

return PdfResponse::streamDownload($doc, 'annual-report.pdf');

Gebruik streamInline() om inline te streamen. Symfony documenteert het callback-contract van StreamedResponse: een void-callable die de uitvoer flusht (https://symfony.com/doc/current/components/http_foundation.html).

Als symfony/messenger is geïnstalleerd, kun je de generatie buiten de request-thread verplaatsen.

Implementeer NextPDF\Symfony\Message\PdfBuilderInterface. De handler geeft je een nieuw, vooraf geconfigureerd Document en de serialiseerbare context uit het bericht.

src/Pdf/InvoicePdfBuilder.php
<?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;
}
}

De handler haalt builders op uit een PHP Standard Recommendation 11 (PSR-11) service-locator, met klassenaam als index. Alleen geregistreerde builders zijn bereikbaar. Voeg de builder toe aan een locator in 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'

De handler vraagt de locator om de builder op basis van de bijbehorende class-string-id. In PSR-11 is een container-identifier een string die een entry uniek identificeert (PSR-11 §1.1.2).

Injecteer Symfony\Component\Messenger\MessageBusInterface en verzend daarna het bericht:

src/Controller/ReportController.php
<?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 is een readonly data transfer object (DTO). De constructor weigert uitvoerpaden die leeg zijn, niet eindigen op .pdf, path-traversal-segmenten bevatten, stream-wrapper-schema’s gebruiken of null bytes bevatten. Hij vereist ook dat builderClass een syntactisch geldige klassenaam is. De handler valideert het uitvoerpad opnieuw tijdens de uitvoering, voordat hij schrijft. Als een pad veilig is bij het verzenden maar onveilig op het moment dat het wordt geconsumeerd, weigert de handler het alsnog. Het attribuut #[AsMessageHandler] en het dispatch-contract van MessageBusInterface volgen het standaard Symfony Messenger-model (https://symfony.com/doc/current/messenger.html).

4d — Het bericht routeren en een worker uitvoeren

Sectie met titel “4d — Het bericht routeren en een worker uitvoeren”

Routeer het bericht in config/packages/messenger.yaml naar een transport:

framework:
messenger:
transports:
async: '%env(MESSENGER_TRANSPORT_DSN)%'
routing:
NextPDF\Symfony\Message\GeneratePdfMessage: async

Voer daarna een worker uit:

Terminal window
php bin/console messenger:consume async
Terminal window
php bin/console debug:container --tag=container.service_locator
php bin/console messenger:consume async --limit=1 -vv

De eerste opdracht bevestigt dat de builder-locator is geregistreerd. De tweede opdracht verwerkt één bericht uit de wachtrij en toont de voortgang van de handler.

  • /integrations/symfony/configuration/ — pas standaardwaarden, lettertypen en de documentservice aan.
  • /integrations/symfony/production-usage/ — bekijk worker-veiligheid en streamen onder belasting.
  • /integrations/symfony/troubleshooting/ — los veelvoorkomende opstart- en runtimeproblemen op.

Elke rij bevat een normatieve bewering op deze pagina en is gekoppeld aan een volledige 64-hex reference_id uit het afgeschermde corpus van de standards development organization (SDO). _sidecars/rag-citations.yaml bevat de herkomst, inclusief het corpusmanifest en het ophaaltransport.

SpecificatieClausulereference_idBewering
PSR-11psr_11_container#1.1.2.p4Identifier-contract voor container-has()/get()
  • /integrations/symfony/overview/ — bekijk het overzicht van de mogelijkheden.
  • /integrations/symfony/install/ — installeer en registreer de bundle.
  • /integrations/symfony/integration/ — bekijk de end-to-end integratiereferentie.