Laravel-Entwicklerleitfaden
Auf einen Blick
Abschnitt betitelt „Auf einen Blick“Das Laravel-Paket richtet NextPDF an den Laravel-Konventionen aus, ohne den zentralen Dokument-Lebenszyklus zu verändern. Der Container verwaltet die gemeinsam genutzten Registries und Factories. Jedes PDF-Dokument ist verwerfbar und sollte genau einmal erstellt, zurückgegeben, gestreamt oder gespeichert werden.
Verwenden Sie diesen Leitfaden, wenn Sie Anwendungsdienste, Queue-Jobs, Response-Abläufe oder die Testabdeckung rund um nextpdf/laravel entwerfen.
Architekturgrenze
Abschnitt betitelt „Architekturgrenze“| Schicht | Im Besitz von | Verantwortung | Hier nicht ablegen |
|---|---|---|---|
| Controller | Anwendung | Anfrage autorisieren, einen Dokument-Builder auswählen und eine Response zurückgeben. | PDF-Layoutregeln, die über mehrere Anwendungsfälle hinweg gemeinsam genutzt werden. |
| Anwendungsdienst | Anwendung | Domänendaten sammeln und den Code zur Dokumenterstellung aufrufen. | Container-Boot-Logik oder Paketkonfiguration. |
| Dokument-Builder | Anwendung | Domänendaten in NextPDF-Dokumentaufrufe übersetzen. | Request-Objekte, Eloquent-Query-Logik oder Details des Queue-Transports. |
| Laravel-Integration | nextpdf/laravel | Bindet Factories, Registries, Signer, TSA-Client, Facade, Responses und Queue-Job. | Geschäftsspezifische Speicherpfade oder Mandantenrichtlinien. |
| Kern-Engine | nextpdf/nextpdf | Baut das PDF und serialisiert es. | Laravel-Response-, Queue- oder Dateisystemrichtlinien. |
Laufzeit-Lebenszyklus
Abschnitt betitelt „Laufzeit-Lebenszyklus“| Phase | Verhalten | Entwickleraktion |
|---|---|---|
| Registrierung des Service-Providers | NextPdfServiceProvider::register() registriert die gemeinsam genutzten Registries, die Dokument-Factory, das Dokument-Binding, den HTTP-Client, den TSA-Client, den Signer und die optionalen E-Invoice-Contracts. | Veröffentlichen Sie config/nextpdf.php und prüfen Sie die Datei vor dem Produktivbetrieb. |
| Dokumentauflösung | Die Pdf-Facade und das PdfDocumentInterface-Binding lösen ein frisches Dokument über DocumentFactoryInterface auf. | Lösen Sie ein Dokument einmal pro Anfrage, Command oder Queue-Job auf. |
| Erstellung | Der Anwendungscode ruft die zentralen Dokument-APIs über die Facade oder das injizierte Dokument auf. | Halten Sie die Extraktion der Domänendaten außerhalb des Dokument-Builders. |
| Endausgabe | PdfResponse gibt die HTTP-Ausgabe aus, oder das Dokument wird auf die Festplatte gespeichert. | Wählen Sie pro Dokument genau einen Pfad für die Endausgabe. |
| Queue-Ausführung | GeneratePdfJob baut das Dokument im Worker neu und validiert den Ausgabepfad erneut. | Übergeben Sie skalaren Kontext und halten Sie Callbacks idempotent. |
Empfohlene Anwendungsstruktur
Abschnitt betitelt „Empfohlene Anwendungsstruktur“| Pfad | Zweck |
|---|---|
app/Pdf/Builders/* | Reine Dokument-Builder. Sie erhalten Daten und geben ein fertiges Dokument zurück. |
app/Pdf/Data/* | Kleine DTOs, die bereits autorisierte Dokumenteingaben transportieren. |
app/Services/* | Anwendungsorchestrierung, Queries, Weitergabe der Autorisierung und Auswahl des Speicherpfads. |
app/Jobs/* | Optionale Wrapper um GeneratePdfJob, wenn die Anwendung benannte Jobs benötigt. |
tests/Feature/Pdf/* | Tests für HTTP-Responses, Queue-Dispatch und Autorisierung. |
tests/Unit/Pdf/* | Builder-Tests mit kleinen, deterministischen Eingaben. |
Halten Sie Builder unabhängig von Laravel-Request-Objekten. Ein Builder sollte mit derselben Eingabe aus einem Controller, einem Command, einem Test und einem Queue-Worker aufrufbar sein.
<?php
namespace App\Pdf\Builders;
use App\Pdf\Data\InvoicePdfData;use NextPDF\Contracts\PdfDocumentInterface;
final readonly class InvoicePdfBuilder{ public function build(PdfDocumentInterface $pdf, InvoicePdfData $data): PdfDocumentInterface { $pdf->setTitle($data->title) ->addPage() ->setFont('dejavusans', '', 12) ->writeHtml($data->html);
return $pdf; }}Synchrones Response-Muster
Abschnitt betitelt „Synchrones Response-Muster“Verwenden Sie Constructor-Injection, wenn der PDF-Ablauf Teil der Anwendungslogik ist. Verwenden Sie die Facade nur für kurze Controller-Abläufe, in denen der statische Stil die Lesbarkeit verbessert.
<?php
namespace App\Http\Controllers;
use App\Pdf\Builders\InvoicePdfBuilder;use App\Pdf\Data\InvoicePdfData;use NextPDF\Contracts\PdfDocumentInterface;use NextPDF\Laravel\Http\PdfResponse;
final readonly class DownloadInvoiceController{ public function __invoke( PdfDocumentInterface $pdf, InvoicePdfBuilder $builder, ) { $document = $builder->build( $pdf, InvoicePdfData::fromInvoiceId(1234), );
return PdfResponse::download($document, 'invoice-1234.pdf'); }}Response-Helfer materialisieren die Dokument-Bytes, bevor die Laravel-Response erstellt wird. Sie sind Response-Helfer, keine Hintergrund-Renderer.
Queue-Muster
Abschnitt betitelt „Queue-Muster“GeneratePdfJob akzeptiert ein Builder-Callable und einen Ausgabepfad. Der Job validiert unsichere Pfade zur Ausführungszeit. Der Anwendungscode sollte dennoch vor dem Dispatch ein mandantensicheres Speicher-Root auswählen.
<?php
use App\Pdf\Builders\QueuedInvoiceBuilder;use NextPDF\Laravel\Jobs\GeneratePdfJob;
GeneratePdfJob::dispatch( outputPath: storage_path('app/pdfs/invoice-1234.pdf'), builder: [QueuedInvoiceBuilder::class, 'build'],)->onQueue(config('nextpdf.queue.queue', 'pdf'));Queue-Callbacks sollten klein bleiben. Schreiben Sie dauerhaften Zustand lieber aus einem Application-Job-Listener heraus, statt komplexe Closures in der Queue-Payload zu speichern.
Erweiterungspunkte
Abschnitt betitelt „Erweiterungspunkte“| Erweiterungspunkt | Nutze es für | Einschränkung |
|---|---|---|
PdfDocumentInterface-Binding | Ersetzen oder Dekorieren der Dokumenterstellung für anwendungsweite Standardwerte. | Muss eine frische Dokumentinstanz zurückgeben. |
DocumentFactoryInterface | Explizites Erzeugen frischer Dokumente in Diensten und Tests. | Zurückgegebene Dokumente nicht cachen. |
config/nextpdf.php | Standardwerte, Queue-Einstellungen, Chrome-Renderer-Einstellungen, Signing-Hooks, TSA und OCSP-Cache. | Behandeln Sie Umgebungsvariablen als Deployment-Konfiguration, nicht als Request-Eingabe. |
GeneratePdfJob-Builder | Dokumente asynchron bauen. | Das Callable muss vom Queue-Transport von Laravel serialisierbar sein. |
| Erfolgs-/Fehler-Callbacks | Benachrichtigungen oder Aufräumarbeiten nach der Generierung. | Halten Sie Callbacks idempotent und berücksichtigen Sie Seiteneffekte. |
| Optionale Premium-Contracts | E-Invoice-Embedder, Validator, Profil und Schematron-Runner. | Lösen Sie sie nur dort auf, wo das optionale Paket installiert und lizenziert ist. |
Entwicklungs-Workflow
Abschnitt betitelt „Entwicklungs-Workflow“- Bauen Sie das erste Dokument synchron in einem Controller oder Feature-Test.
- Verschieben Sie den Layout-Code in eine Builder-Klasse unter
app/Pdf/Builders. - Verschieben Sie Query- und Autorisierungslogik in einen Anwendungsdienst.
- Fügen Sie
PdfResponse-Tests für Header und Dateinamen hinzu. - Verschieben Sie langsame oder hochvolumige Generierung nach
GeneratePdfJob. - Fügen Sie Queue-Tests für serialisierten Kontext, die Ausgabepfad-Richtlinie und die Fehlerbehandlung hinzu.
- Messen Sie Speicherverbrauch und Renderzeit mit repräsentativen Produktionsdaten.
Fehlerbehandlung
Abschnitt betitelt „Fehlerbehandlung“| Fehler | Wo er behandelt werden sollte | Empfohlene Reaktion |
|---|---|---|
| Ungültige Anfrage oder nicht autorisiertes Dokument | Controller oder Policy. | Geben Sie die normale Autorisierungs- oder Validierungs-Response der Anwendung zurück. |
| Fehlende Schrift oder ungültiges Bild | Builder-Test und Anwendungs-Logging. | Lassen Sie die Anfrage oder den Job fehlschlagen; geben Sie keine unvollständigen PDFs aus. |
| Unsicherer Ausgabepfad | Speicherdienst der Anwendung und GeneratePdfJob. | Lehnen Sie ihn vor dem Dispatch ab und verlassen Sie sich auf die Validierung auf Worker-Seite als Verteidigung in der Tiefe. |
| Signing- oder TSA-Fehler | Grenze zum Signing-Dienst. | Entscheiden Sie, ob das Dokument unsigniert sein darf; bei regulierten Dokumenten standardmäßig fail-closed. |
| Queue-Timeout | Konfiguration und Observability des Queue-Workers. | Wiederholen Sie nur, wenn der Builder deterministisch ist und der Ausgabepfad sicher überschrieben werden darf. |
Sichere Standardwerte
Abschnitt betitelt „Sichere Standardwerte“| Aspekt | Standardwert | Wann überschreiben |
|---|---|---|
| Queue-Name | pdf | Verwenden Sie eine eigene Queue, wenn die Generierung mit nutzerseitigen Jobs konkurriert. |
| Job-Timeout | 120 Sekunden | Erhöhen Sie ihn erst, nachdem Sie Dokumentgröße und Worker-Kapazität gemessen haben. |
| Response-Dateiname | document.pdf | Verwenden Sie bereinigte Geschäftskennungen. |
| Font-Registry | Gemeinsam genutzt und nach dem Warmup gesperrt. | Fügen Sie preload_fonts für Schriften hinzu, die auf heißen Pfaden genutzt werden. |
| Image-Registry | Gemeinsam genutzter, begrenzter Cache. | Senken Sie image_cache_mb für Worker mit knappem Speicher. |
| Chunking der gestreamten Response | 64-KB-Chunks. | Verlassen Sie sich nicht auf Chunk-Grenzen; sie sind ein Ausgabedetail. |
Test-Checkliste
Abschnitt betitelt „Test-Checkliste“- Controller-Tests prüfen
Content-Type,Content-Dispositionund defensive Header. - Builder-Tests verwenden deterministische DTOs und greifen nicht auf die Datenbank zu.
- Queue-Tests prüfen, dass der Builder ein frisches Dokument erhält.
- Pfad-Tests decken Traversal, Stream-Wrapper, Null-Bytes und die Ablehnung von Nicht-
.pdf-Dateien ab. - Worker-Tests rendern repräsentative Dokumente unter demselben Speicherlimit wie in der Produktion.
- Optionale Signing-Tests decken fehlendes Zertifikat, ungültiges Passwort, nicht verfügbare TSA und das konfigurierte Signaturniveau ab.