Быстрый старт с NextPDF для Symfony
Краткий обзор
Заголовок раздела «Краткий обзор»Внедрите PdfFactory, создайте Document и верните его через PdfResponse. Если нужно формирование в фоне, отправьте GeneratePdfMessage в транспорт Messenger.
Шаг 1 — формирование PDF в контроллере
Заголовок раздела «Шаг 1 — формирование PDF в контроллере»Внедрите NextPDF\Symfony\Service\PdfFactory. Метод create() возвращает новый NextPDF\Core\Document. Он применяет заданные вами значения по умолчанию для приложения-создателя, автора и языка. Верните документ через 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() возвращает Symfony\Component\HttpFoundation\Response. Он задаёт Content-Type: application/pdf, заголовок Content-Disposition со значением attachment, Content-Length, а также фиксированные заголовки безопасности бандла. Стандартный класс Response и модель его заголовков описаны в документации Symfony (https://symfony.com/doc/current/components/http_foundation.html).
Шаг 2 — отображение PDF в окне браузера
Заголовок раздела «Шаг 2 — отображение PDF в окне браузера»Используйте inline(), если браузер должен показать PDF, а не загрузить его:
return PdfResponse::inline($doc, 'preview.pdf');Заголовок Content-Disposition получает значение inline. Все остальные заголовки остаются прежними.
Шаг 3 — потоковая передача большого PDF
Заголовок раздела «Шаг 3 — потоковая передача большого PDF»Для больших документов используйте потоковые методы. Они отдают PDF фрагментами по 64 KB, что снижает пиковое потребление памяти. Эти методы возвращают Symfony\Component\HttpFoundation\StreamedResponse и не задают Content-Length.
return PdfResponse::streamDownload($doc, 'annual-report.pdf');Для потоковой передачи в браузере используйте streamInline(). В документации Symfony описан контракт обратного вызова StreamedResponse: это вызываемый объект, возвращающий void и сбрасывающий вывод (https://symfony.com/doc/current/components/http_foundation.html).
Шаг 4 — асинхронное формирование PDF
Заголовок раздела «Шаг 4 — асинхронное формирование PDF»Если установлен symfony/messenger, вы можете вынести формирование за пределы обработки запроса.
4a — реализация сборщика
Заголовок раздела «4a — реализация сборщика»Реализуйте NextPDF\Symfony\Message\PdfBuilderInterface. Обработчик передаёт вам новый, предварительно настроенный Document и сериализуемый контекст из сообщения.
<?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 — регистрация сборщика в локаторе
Заголовок раздела «4b — регистрация сборщика в локаторе»Обработчик получает сборщики из локатора служб PHP Standard Recommendation 11 (PSR-11), где ключом служит имя класса. Доступны только зарегистрированные сборщики. Добавьте сборщик в локатор в файле 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'Обработчик запрашивает у локатора сборщик по идентификатору class-string. В PSR-11 идентификатор контейнера — это строка, которая однозначно идентифицирует запись (PSR-11 §1.1.2).
4c — отправка сообщения
Заголовок раздела «4c — отправка сообщения»Внедрите Symfony\Component\Messenger\MessageBusInterface, затем отправьте сообщение:
<?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 — это объект передачи данных (DTO) с модификатором readonly. Его конструктор отклоняет пути вывода, которые пусты, не заканчиваются на .pdf, содержат сегменты обхода каталогов, используют схемы stream-wrapper или содержат нулевые байты. Кроме того, он требует, чтобы builderClass был синтаксически корректным именем класса. Обработчик повторно проверяет путь вывода во время выполнения перед записью. Если путь безопасен при отправке, но небезопасен в момент обработки, обработчик всё равно отклоняет его. Атрибут #[AsMessageHandler] и контракт отправки MessageBusInterface следуют стандартной модели Symfony Messenger (https://symfony.com/doc/current/messenger.html).
4d — маршрутизация сообщения и запуск воркера
Заголовок раздела «4d — маршрутизация сообщения и запуск воркера»В файле config/packages/messenger.yaml направьте сообщение в транспорт:
framework: messenger: transports: async: '%env(MESSENGER_TRANSPORT_DSN)%' routing: NextPDF\Symfony\Message\GeneratePdfMessage: asyncЗатем запустите воркер:
php bin/console messenger:consume asyncПроверка работоспособности
Заголовок раздела «Проверка работоспособности»php bin/console debug:container --tag=container.service_locatorphp bin/console messenger:consume async --limit=1 -vvПервая команда подтверждает, что локатор сборщиков зарегистрирован. Вторая команда обрабатывает одно сообщение из очереди и показывает ход выполнения обработчика.
Дальнейшие шаги
Заголовок раздела «Дальнейшие шаги»- /integrations/symfony/configuration/ — настройте значения по умолчанию, шрифты и службу документов.
- /integrations/symfony/production-usage/ — ознакомьтесь с безопасностью воркеров и потоковой передачей под нагрузкой.
- /integrations/symfony/troubleshooting/ — устраните типичные проблемы запуска и выполнения.
Соответствие стандартам
Заголовок раздела «Соответствие стандартам»Каждая строка представляет нормативное утверждение с этой страницы, привязанное к полному 64-значному шестнадцатеричному reference_id из закрытого корпуса организации по разработке стандартов (SDO). _sidecars/rag-citations.yaml содержит сведения о происхождении, включая манифест корпуса и транспорт получения данных.
| Спецификация | Пункт | reference_id (идентификатор ссылки) | Утверждение |
|---|---|---|---|
| PSR-11 | psr_11_container#1.1.2.p4 | Контракт идентификатора has()/get() контейнера |
Смотрите также
Заголовок раздела «Смотрите также»- /integrations/symfony/overview/ — ознакомьтесь со сводкой возможностей.
- /integrations/symfony/install/ — установите и зарегистрируйте бандл.
- /integrations/symfony/integration/ — ознакомьтесь со сквозным справочником по интеграции.