Het NextPDF Laravel-pakket in productie gebruiken
In een oogopslag
Sectie met titel “In een oogopslag”Laat het documentcontract in productie via constructor-injectie oplossen. Handel mislukte PDF-schrijfbewerkingen af met een specifieke exception. Verplaats zware generatie of batchgeneratie naar GeneratePdfJob en koppel expliciete callbacks voor succes en mislukking.
Installeren
Sectie met titel “Installeren”composer require nextpdf/laravelphp artisan vendor:publish --tag=nextpdf-configConfigureer de wachtrijverbinding in config/nextpdf.php. Stel queue.connection, queue.queue en queue.timeout in. Zorg er vervolgens voor dat er een worker draait op de geconfigureerde verbinding.
Conceptueel overzicht
Sectie met titel “Conceptueel overzicht”De container stelt NextPDF\Contracts\PdfDocumentInterface beschikbaar als een factory-binding. Elke resolutie levert een nieuw NextPDF\Core\Document op. PSR-11 staat toe dat een container verschillende waarden teruggeeft bij opeenvolgende get()-aanroepen, afhankelijk van de bindingstrategie (PSR-11 §1.1.2). Dit pakket gebruikt een factory-binding zodat veranderlijke status binnen het bereik van een verzoek nooit naar een ander verzoek overgaat. De registries voor lettertypen en afbeeldingen zijn singletons. Daarmee blijft het contract behouden dat een gebonden identifier wordt opgelost naar zijn geregistreerde vermelding (PSR-11 §1.1.2), terwijl de dure resources toch tijdens de levensduur van de worker worden gedeeld.
Geef in productiecode de voorkeur aan constructor-injectie boven de facade. Dit maakt de afhankelijkheid expliciet en houdt de controller unit-testbaar zonder de facade-root op te starten.
Codevoorbeeld — productie
Sectie met titel “Codevoorbeeld — productie”Controller met DI en getypeerde foutafhandeling
Sectie met titel “Controller met DI en getypeerde foutafhandeling”<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use Illuminate\Http\Response;use NextPDF\Contracts\PdfDocumentInterface;use NextPDF\Laravel\Http\PdfResponse;use Psr\Log\LoggerInterface;use Throwable;
final class InvoiceController extends Controller{ public function __construct( private readonly PdfDocumentInterface $document, private readonly LoggerInterface $logger, ) {}
public function show(int $invoiceId): Response { try { $this->document->addPage(); $this->document->cell(0, 10, "Invoice #{$invoiceId}", newLine: true); $this->document->cell(0, 10, 'Thank you for your business.');
return PdfResponse::download( $this->document, "invoice-{$invoiceId}.pdf", ); } catch (Throwable $exception) { // Rethrow as an HTTP-meaningful failure; never swallow. $this->logger->error('Invoice PDF generation failed', [ 'invoice_id' => $invoiceId, 'exception' => $exception::class, ]);
return new Response('Could not generate the invoice PDF.', 500); } }}Injecteer PdfDocumentInterface, niet de concrete Document, zodat je de binding in tests kunt vervangen. De container geeft een nieuw document terug telkens wanneer de controller wordt geïnstantieerd. Hergebruik niet dezelfde controller-instantie voor twee niet-gerelateerde documenten binnen één proces.
Het catch-blok logt de exception-klasse en geeft een expliciete HTTP-fout terug in plaats van een stacktrace te lekken. Gebruik Psr\Log\LoggerInterface, die door de container naar de framework-logger wordt opgelost. PSR-3 laat het escapen van placeholders over aan de implementator en draagt aanroepers op om contextwaarden niet vooraf te escapen (PSR-3 §1.2). Geef gestructureerde context door, geen geïnterpoleerde strings.
Generatie in de wachtrij met callbacks voor succes en mislukking
Sectie met titel “Generatie in de wachtrij met callbacks voor succes en mislukking”GeneratePdfJob is een ShouldQueue-job. Standaard gebruikt deze drie pogingen, een time-out van 120 seconden en een backoff van 10 seconden. Je kunt alle drie overschrijven in config/nextpdf.php. De builder-closure ontvangt het document dat door de container is opgelost en moet een geconfigureerd document teruggeven.
<?php
declare(strict_types=1);
namespace App\Jobs;
use NextPDF\Contracts\PdfDocumentInterface;use NextPDF\Laravel\Jobs\GeneratePdfJob;use Psr\Log\LoggerInterface;use Throwable;
final class DispatchMonthlyStatement{ public function __construct(private readonly LoggerInterface $logger) {}
public function __invoke(int $accountId): void { // Dispatchable::dispatch() is `public static`: it constructs the // job from the arguments it receives and returns a PendingDispatch. // Pass every constructor argument — including the callbacks — to // the static call. Building an instance and then calling // `$job->dispatch(...)` would discard that instance (and its // callbacks) and queue a different job from only the static args. GeneratePdfJob::dispatch( storage_path("app/statements/{$accountId}.pdf"), static fn (PdfDocumentInterface $document): PdfDocumentInterface => $document ->addPage() ->cell(0, 10, "Statement for account {$accountId}", newLine: true), function (string $path) use ($accountId): void { $this->logger->info('Statement PDF written', [ 'account_id' => $accountId, 'path' => $path, ]); }, function (Throwable $exception) use ($accountId): void { $this->logger->error('Statement PDF failed', [ 'account_id' => $accountId, 'exception' => $exception::class, ]); }, ); }}GeneratePdfJob::dispatch() stuurt zijn argumenten rechtstreeks door naar de constructor (string $outputPath, callable $builder, ?callable $onSuccess, ?callable $onFailure). Daardoor worden de callbacks voor succes en mislukking gekoppeld aan dezelfde job die in de wachtrij wordt geplaatst. Dit komt overeen met de positionele GeneratePdfJob::dispatch($path, $builder)-vorm in /integrations/laravel/quickstart/. De succes-callback ontvangt het uitvoerpad en de mislukkings-callback ontvangt de Throwable. De job stelt ook fluent setters then() en catch() beschikbaar die de job teruggeven voor chaining. Gebruik die setters alleen wanneer je diezelfde instantie behoudt en verzendt, bijvoorbeeld via de dispatch()-helper. De job stelt ook een methode failed() beschikbaar, die door de wachtrij-runner wordt aangeroepen bij een definitieve mislukking. Callbacks worden verpakt in serialiseerbare closures, zodat ze het wachtrijtransport overleven.
Wachtrijgedrag afstemmen
Sectie met titel “Wachtrijgedrag afstemmen”| Eigenschap | Standaard | Configuratiesleutel |
|---|---|---|
tries | 3 | niet via configuratie gestuurd; maak een subklasse om te wijzigen |
timeout | 120 | nextpdf.queue.timeout |
backoff | 10 | niet via configuratie gestuurd; maak een subklasse om te wijzigen |
| wachtrijnaam | pdf | nextpdf.queue.queue |
| verbinding | standaard | nextpdf.queue.connection |
tries en backoff zijn publieke eigenschappen die uit de job-instantie worden gelezen. De meegeleverde job leest ze niet uit de configuratie. Als je beleid voor nieuwe pogingen afwijkt, maak dan een subklasse van GeneratePdfJob om ze te overschrijven.
Randgevallen en valkuilen
Sectie met titel “Randgevallen en valkuilen”- De builder-closure moet een
PdfDocumentInterfaceteruggeven. De job slaat die retourwaarde op, niet de oorspronkelijk opgeloste instantie. De job-test controleert dit contract expliciet. - Het oplossen van
SignerInterfacegeeftnullterug, tenzij ondertekening is ingeschakeld, een certificaat is geconfigureerd ennextpdf/premiumis geïnstalleerd. Controleer altijd op null voordat je ondertekent. - Langlevende workers (Octane/RoadRunner/Swoole) delen de vergrendelde lettertype-registry. Configureer
preload_fontszodat de opwarming één keer bij het opstarten van de worker plaatsvindt in plaats van bij het eerste verzoek. - Voor een mislukte job wordt
failed()aangeroepen nadattrieszijn uitgeput. Een mislukking per poging roeptonFailureniet aan; dat gebeurt pas wanneer de wachtrij-runner een definitieve mislukking verklaart.
Prestaties
Sectie met titel “Prestaties”Synchrone generatie in de controller blokkeert het verzoek tijdens de volledige PDF-opbouw. Verzend GeneratePdfJob voor uitvoer met meerdere pagina’s of batchuitvoer en keer onmiddellijk terug. De singleton-registries spreiden het parsen van lettertypen en het decoderen van afbeeldingen over de levensduur van de worker. De kosten per verzoek blijven dan beperkt tot het opbouwen van het document en het uitvoeren van de inhoud.
Beveiligingsopmerkingen
Sectie met titel “Beveiligingsopmerkingen”De controller met dependency-injection logt de exception-klasse, niet de bijbehorende boodschap of trace, om te voorkomen dat interne details in de logs lekken. GeneratePdfJob valideert het uitvoerpad op de worker om gemanipuleerde geserialiseerde payloads via het wachtrijtransport te beperken. De volledige behandeling staat in /integrations/laravel/security-and-operations/.
Conformiteit
Sectie met titel “Conformiteit”| Bewering | Bron | Clausule | reference_id |
|---|---|---|---|
| Gebonden identifier wordt opgelost naar zijn geregistreerde vermelding | PSR-11 Container | §1.1.2 | |
| Opeenvolgende resoluties kunnen verschillen per bindingstrategie (factory-binding) | PSR-11 Container | §1.1.2 |
De PSR-3-loggingrichtlijnen staan in de PSR-3-specificatie. Die richtlijn wijst het escapen van placeholders toe aan de implementator en draagt aanroepers op om gestructureerde context door te geven. Zie document psr_3_logger §1.2.
Commerciële context
Sectie met titel “Commerciële context”Ondertekende PAdES B-B-uitvoer en PDF/A-archivering via nextpdf/premium gebruiken hetzelfde dependency-injection-oppervlak (DI). Dit is een optionele Enterprise-functionaliteit. Voor het hier gedocumenteerde Core-pakket is geen codewijziging nodig om dit over te nemen. Zie https://nextpdf.dev/get-license/?intent=laravel-signing.
Zie ook
Sectie met titel “Zie ook”- /integrations/laravel/quickstart/ — minimaal beginvoorbeeld
- /integrations/laravel/configuration/ — sleutels voor wachtrij, handtekening en lettertype
- /integrations/laravel/security-and-operations/ — dreigingsmodel en hardening
- /integrations/laravel/troubleshooting/ — veelvoorkomende productiefouten