Skip to content

NextPDF Symfony integration

Install nextpdf/symfony, let Flex register the bundle or register it yourself, add config/packages/nextpdf.yaml, and inject PdfFactory. Use this page as the wiring index. Each step points to a deeper guide.

Terminal window
composer require nextpdf/symfony

The bundle requires nextpdf/core^3.0 || ^5.2, symfony/*^7.2, and psr/log^3.0. Classes autoload under the PHP Standards Recommendation (PSR)-4 prefix NextPDF\Symfony\, mapped to src/Symfony/. A PSR-4 autoloader maps that namespace prefix to the base directory (PSR-4 §2). For full requirements and optional packages, see /integrations/symfony/install/.

With Symfony Flex, the extra.symfony.bundles entry in the bundle composer.json registers NextPDF\Symfony\NextPdfBundle for all environments. Without Flex, add it to config/bundles.php yourself:

return [
NextPDF\Symfony\NextPdfBundle::class => ['all' => true],
];

For the full boot sequence and compiler-pass behavior, see /integrations/symfony/boot-and-discovery/.

The bundle’s config/services.php file registers these services:

Service / aliasLifecycle
NextPDF\Symfony\Service\PdfFactoryshared, public; inject this
nextpdf.documentPdfDocumentInterfaceDocumentnon-shared, public; fresh per resolve
NextPDF\Contracts\FontRegistryInterfaceshared, locked after warmup
NextPDF\Graphics\ImageRegistryshared, kernel.reset
NextPDF\Contracts\DocumentFactoryInterfaceshared
NextPDF\Symfony\Http\PdfResponsepublic, stateless helper

The document binding is deliberately non-shared. PSR-11 permits a container to return different values on successive get() calls for one identifier. A fresh document avoids cross-request state in long-running workers (PSR-11 §1.1.2). For the complete service and alias table, including conditional EInvoice bindings, see /integrations/symfony/configuration/.

The configuration alias is nextpdf. Create config/packages/nextpdf.yaml. When Flex publishes a recipe, it adds a default copy for you. Every key has a default value, so a minimal file looks like this:

nextpdf: ~

The full configuration tree is documented in /integrations/symfony/configuration/.

Inject PdfFactory, then return the document with PdfResponse:

src/Controller/PdfController.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 PdfController
{
#[Route('/hello.pdf', name: 'hello_pdf')]
public function hello(PdfFactory $pdf): Response
{
$doc = $pdf->create();
$doc->addPage();
$doc->cell(0, 10, 'Hello from NextPDF on Symfony.');
return PdfResponse::inline($doc, 'hello.pdf');
}
}

For the end-to-end controller and the Messenger asynchronous path, see /integrations/symfony/quickstart/.

Verify the wiring without writing application code:

Terminal window
php bin/console debug:container nextpdf
php bin/console debug:config nextpdf
php bin/console lint:container

debug:container nextpdf should list PdfFactory, the nextpdf.document alias, and the registries. lint:container checks that every service argument resolves. To test generation, add the controller above, then request /hello.pdf.

The application programming interface (API) surface supports these public symbols for application code:

SymbolPurpose
NextPDF\Symfony\Service\PdfFactory::create()fresh, pre-configured Document
NextPDF\Symfony\Http\PdfResponse::inline() / download()buffered response with security headers
NextPDF\Symfony\Http\PdfResponse::streamInline() / streamDownload()chunked streamed response
NextPDF\Symfony\Message\GeneratePdfMessageasynchronous generation data transfer object (DTO) (validated)
NextPDF\Symfony\Message\PdfBuilderInterfacebuilder contract resolved by the handler

Each row lists a normative claim made on this page. Each claim is pinned to a full 64-hex reference_id from the gated standards development organization (SDO) corpus. Provenance (corpus manifest and retrieval transport) is in _sidecars/rag-citations.yaml.

SpecClausereference_idClaim
PSR-11psr_11_container#1.1.2.p4Container has()/get() identifier contract
PSR-4psr_4_autoload#x1.x2.p5Autoloader namespace mapping
  • /integrations/symfony/install/ — requirements and registration.
  • /integrations/symfony/boot-and-discovery/ — discovery, boot, and compiler pass.
  • /integrations/symfony/configuration/ — full schema and service table.
  • /integrations/symfony/quickstart/ — runnable controller and async example.
  • /integrations/symfony/production-usage/ — worker safety and streaming.