Przejdź do głównej zawartości

NextPDF Symfony — szybki start

Wstrzyknij PdfFactory, zbuduj Document i zwróć go przez PdfResponse. Gdy potrzebujesz generowania w tle, wyślij komunikat GeneratePdfMessage do transportu Messengera.

Wstrzyknij NextPDF\Symfony\Service\PdfFactory. Metoda create() zwraca nowy obiekt NextPDF\Core\Document i stosuje skonfigurowane wartości domyślne dla twórcy, autora oraz języka. Zwróć dokument przez 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() zwraca obiekt Symfony\Component\HttpFoundation\Response. Ustawia Content-Type: application/pdf, dyspozycję attachment, Content-Length oraz stałe nagłówki bezpieczeństwa pakietu. W dokumentacji Symfony opisano standardową klasę Response oraz jej model nagłówków (https://symfony.com/doc/current/components/http_foundation.html).

Użyj inline(), gdy chcesz, aby przeglądarka wyświetliła plik PDF zamiast go pobierać:

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

Dyspozycja zostaje ustawiona na inline. Wszystkie pozostałe nagłówki pozostają bez zmian.

W przypadku dużych dokumentów użyj wariantów strumieniowych. Wysyłają plik PDF w porcjach po 64 KB, co zmniejsza szczytowe zużycie pamięci. Zwracają obiekt Symfony\Component\HttpFoundation\StreamedResponse i pomijają Content-Length.

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

Użyj streamInline() do strumieniowania w trybie inline. W dokumentacji Symfony opisano kontrakt wywołania zwrotnego StreamedResponse: jest to funkcja typu void, która opróżnia bufor wyjściowy (https://symfony.com/doc/current/components/http_foundation.html).

Gdy zainstalowany jest symfony/messenger, możesz przenieść generowanie poza wątek obsługi żądania.

Zaimplementuj NextPDF\Symfony\Message\PdfBuilderInterface. Procedura obsługi przekazuje nowy, wstępnie skonfigurowany obiekt Document oraz serializowalny kontekst z komunikatu.

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

Procedura obsługi rozwiązuje buildery z lokatora usług zgodnego z PHP Standard Recommendation 11 (PSR-11), w którym kluczem jest nazwa klasy. Dostępne są wyłącznie zarejestrowane buildery. Dodaj builder do lokatora w pliku 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'

Procedura obsługi pobiera builder z lokatora, używając identyfikatora będącego łańcuchem z nazwą klasy. W PSR-11 identyfikator kontenera to łańcuch, który jednoznacznie identyfikuje wpis (PSR-11 §1.1.2).

Wstrzyknij Symfony\Component\Messenger\MessageBusInterface, a następnie wyślij komunikat:

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 to obiekt transferu danych (DTO) z atrybutem readonly. Jego konstruktor odrzuca ścieżki wyjściowe, które są puste, nie kończą się na .pdf, zawierają segmenty path traversal, używają schematów stream wrapper lub zawierają bajty zerowe. Wymaga również, aby builderClass był składniowo poprawną nazwą klasy. Procedura obsługi ponownie weryfikuje ścieżkę wyjściową w czasie wykonania, zanim zapisze plik. Jeśli ścieżka jest bezpieczna w chwili wysyłki, ale niebezpieczna w chwili konsumpcji, procedura obsługi i tak ją odrzuca. Atrybut #[AsMessageHandler] oraz kontrakt wysyłki MessageBusInterface są zgodne ze standardowym modelem Symfony Messenger (https://symfony.com/doc/current/messenger.html).

W pliku config/packages/messenger.yaml skieruj komunikat do transportu:

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

Następnie uruchom worker:

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

Pierwsze polecenie potwierdza, że lokator builderów jest zarejestrowany. Drugie polecenie konsumuje jeden zakolejkowany komunikat i wyświetla postęp działania procedury obsługi.

  • /integrations/symfony/configuration/ — dostosuj wartości domyślne, czcionki oraz usługę dokumentów.
  • /integrations/symfony/production-usage/ — zapoznaj się z bezpieczeństwem workerów oraz strumieniowaniem pod obciążeniem.
  • /integrations/symfony/troubleshooting/ — rozwiąż typowe problemy z uruchamianiem i działaniem.

Każdy wiersz zawiera normatywne twierdzenie z tej strony, powiązane z pełnym, 64-znakowym szesnastkowym reference_id z zamkniętego korpusu organizacji opracowującej standardy (SDO). _sidecars/rag-citations.yaml zawiera informacje o pochodzeniu, w tym manifest korpusu oraz transport pobierania.

SpecyfikacjaKlauzulareference_idTwierdzenie
PSR-11psr_11_container#1.1.2.p4Kontrakt identyfikatora kontenera has()/get()
  • /integrations/symfony/overview/ — zapoznaj się z podsumowaniem możliwości.
  • /integrations/symfony/install/ — zainstaluj i zarejestruj pakiet.
  • /integrations/symfony/integration/ — zapoznaj się z kompleksowym opisem integracji.