NextPDF Symfony — szybki start
W skrócie
Dział zatytułowany „W skrócie”Wstrzyknij PdfFactory, zbuduj Document i zwróć go przez PdfResponse. Gdy potrzebujesz generowania w tle, wyślij komunikat GeneratePdfMessage do transportu Messengera.
Krok 1 — wygeneruj plik PDF w kontrolerze
Dział zatytułowany „Krok 1 — wygeneruj plik PDF w kontrolerze”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.
<?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).
Krok 2 — wyświetl plik PDF w trybie inline
Dział zatytułowany „Krok 2 — wyświetl plik PDF w trybie inline”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.
Krok 3 — strumieniuj duży plik PDF
Dział zatytułowany „Krok 3 — strumieniuj duży plik PDF”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).
Krok 4 — wygeneruj plik PDF asynchronicznie
Dział zatytułowany „Krok 4 — wygeneruj plik PDF asynchronicznie”Gdy zainstalowany jest symfony/messenger, możesz przenieść generowanie poza wątek obsługi żądania.
4a — zaimplementuj builder
Dział zatytułowany „4a — zaimplementuj builder”Zaimplementuj NextPDF\Symfony\Message\PdfBuilderInterface. Procedura obsługi przekazuje nowy, wstępnie skonfigurowany obiekt Document oraz serializowalny kontekst z komunikatu.
<?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 — zarejestruj builder w lokatorze
Dział zatytułowany „4b — zarejestruj builder w lokatorze”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).
4c — wyślij komunikat
Dział zatytułowany „4c — wyślij komunikat”Wstrzyknij Symfony\Component\Messenger\MessageBusInterface, a następnie wyślij komunikat:
<?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).
4d — wyznacz trasę komunikatu i uruchom worker
Dział zatytułowany „4d — wyznacz trasę komunikatu i uruchom worker”W pliku config/packages/messenger.yaml skieruj komunikat do transportu:
framework: messenger: transports: async: '%env(MESSENGER_TRANSPORT_DSN)%' routing: NextPDF\Symfony\Message\GeneratePdfMessage: asyncNastępnie uruchom worker:
php bin/console messenger:consume asyncSprawdź, czy działa
Dział zatytułowany „Sprawdź, czy działa”php bin/console debug:container --tag=container.service_locatorphp bin/console messenger:consume async --limit=1 -vvPierwsze polecenie potwierdza, że lokator builderów jest zarejestrowany. Drugie polecenie konsumuje jeden zakolejkowany komunikat i wyświetla postęp działania procedury obsługi.
Następne kroki
Dział zatytułowany „Następne kroki”- /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.
Zgodność
Dział zatytułowany „Zgodność”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.
| Specyfikacja | Klauzula | reference_id | Twierdzenie |
|---|---|---|---|
| PSR-11 | psr_11_container#1.1.2.p4 | Kontrakt identyfikatora kontenera has()/get() |
Zobacz też
Dział zatytułowany „Zobacz też”- /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.