Użycie produkcyjne pakietu NextPDF dla Laravela
W skrócie
Dział zatytułowany „W skrócie”W środowisku produkcyjnym rozwiązuj kontrakt dokumentu przez wstrzykiwanie przez konstruktor. Obsługuj niepowodzenia zapisu pliku PDF za pomocą konkretnego wyjątku. Ciężkie lub wsadowe generowanie przenieś do GeneratePdfJob i podłącz jawne wywołania zwrotne sukcesu i niepowodzenia.
Instalacja
Dział zatytułowany „Instalacja”composer require nextpdf/laravelphp artisan vendor:publish --tag=nextpdf-configSkonfiguruj połączenie kolejki w pliku config/nextpdf.php. Ustaw queue.connection, queue.queue oraz queue.timeout. Następnie upewnij się, że proces roboczy działa na skonfigurowanym połączeniu.
Przegląd koncepcyjny
Dział zatytułowany „Przegląd koncepcyjny”Kontener udostępnia NextPDF\Contracts\PdfDocumentInterface jako powiązanie fabryczne. Każde rozwiązanie zależności zwraca świeży obiekt NextPDF\Core\Document. PSR-11 zezwala kontenerowi na zwracanie różnych wartości z kolejnych wywołań get(), w zależności od strategii powiązania (PSR-11 §1.1.2). Ten pakiet korzysta z powiązania fabrycznego, dzięki czemu zmienny stan ograniczony do żądania nigdy nie przechodzi między żądaniami. Rejestry czcionek i obrazów są singletonami. Dzięki temu zachowany jest kontrakt, zgodnie z którym powiązany identyfikator jest rozwiązywany do zarejestrowanego wpisu (PSR-11 §1.1.2), a jednocześnie kosztowne zasoby nadal są współdzielone w obrębie procesu roboczego.
W kodzie produkcyjnym preferuj wstrzykiwanie przez konstruktor zamiast fasady. Dzięki temu zależność jest jawna, a kontroler można testować jednostkowo bez uruchamiania korzenia fasady.
Przykład kodu — produkcja
Dział zatytułowany „Przykład kodu — produkcja”Kontroler z wstrzykiwaniem zależności i typowaną obsługą błędów
Dział zatytułowany „Kontroler z wstrzykiwaniem zależności i typowaną obsługą błędów”<?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); } }}Wstrzykuj PdfDocumentInterface, a nie konkretny Document, aby móc podmieniać powiązanie w testach. Kontener zwraca świeży dokument przy każdym utworzeniu instancji kontrolera. Nie używaj ponownie tej samej instancji kontrolera dla dwóch niepowiązanych dokumentów w obrębie jednego procesu.
Blok catch rejestruje klasę wyjątku i zwraca kontrolowany błąd HTTP zamiast ujawniać ślad stosu. Użyj Psr\Log\LoggerInterface, który kontener rozwiązuje do mechanizmu rejestrowania frameworka. PSR-3 pozostawia escapowanie symboli zastępczych implementatorowi i nakazuje wywołującym, aby nie escapowali wstępnie wartości kontekstu (PSR-3 §1.2). Przekazuj ustrukturyzowany kontekst, a nie interpolowane ciągi znaków.
Kolejkowane generowanie z wywołaniami zwrotnymi sukcesu i niepowodzenia
Dział zatytułowany „Kolejkowane generowanie z wywołaniami zwrotnymi sukcesu i niepowodzenia”GeneratePdfJob to zadanie ShouldQueue. Domyślnie wykonuje trzy próby, ma limit czasu 120 sekund oraz 10-sekundowy backoff. Wszystkie trzy wartości możesz nadpisać w pliku config/nextpdf.php. Domknięcie budujące dokument otrzymuje dokument rozwiązany przez kontener i musi zwrócić skonfigurowany dokument.
<?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() przekazuje swoje argumenty bezpośrednio do konstruktora (string $outputPath, callable $builder, ?callable $onSuccess, ?callable $onFailure). W rezultacie wywołania zwrotne sukcesu i niepowodzenia są podłączone do tego samego zadania, które trafia do kolejki. Odpowiada to pozycyjnej formie GeneratePdfJob::dispatch($path, $builder) z /integrations/laravel/quickstart/. Wywołanie zwrotne sukcesu otrzymuje ścieżkę wyjściową, a wywołanie zwrotne niepowodzenia otrzymuje obiekt Throwable. Zadanie udostępnia również płynne settery then() oraz catch(), które zwracają zadanie i umożliwiają łączenie wywołań. Tych setterów używaj tylko wtedy, gdy zachowujesz i wysyłasz tę samą instancję, na przykład za pomocą funkcji pomocniczej dispatch(). Zadanie udostępnia także metodę failed(), którą mechanizm kolejki wywołuje przy niepowodzeniu terminalnym. Wywołania zwrotne są opakowane w domknięcia możliwe do serializacji, dzięki czemu przetrwają transport kolejki.
Dostrajanie zachowania kolejki
Dział zatytułowany „Dostrajanie zachowania kolejki”| Właściwość | Wartość domyślna | Klucz konfiguracji |
|---|---|---|
tries | 3 | nie jest sterowane konfiguracją; aby zmienić, utwórz podklasę |
timeout | 120 | nextpdf.queue.timeout |
backoff | 10 | nie jest sterowane konfiguracją; aby zmienić, utwórz podklasę |
| nazwa kolejki | pdf | nextpdf.queue.queue |
| połączenie | domyślne | nextpdf.queue.connection |
tries oraz backoff to właściwości publiczne odczytywane z instancji zadania. Zadanie dostarczane z pakietem nie odczytuje ich z konfiguracji. Jeśli obowiązuje inna polityka ponawiania, utwórz podklasę GeneratePdfJob, aby je nadpisać.
Przypadki brzegowe i pułapki
Dział zatytułowany „Przypadki brzegowe i pułapki”- Domknięcie budujące musi zwrócić
PdfDocumentInterface. Zadanie zapisuje zwróconą wartość, a nie pierwotnie rozwiązaną instancję. Test zadania jawnie weryfikuje ten kontrakt. - Rozwiązanie
SignerInterfacezwracanull, chyba że podpisywanie jest włączone, certyfikat jest skonfigurowany oraz zainstalowanonextpdf/premium. Zawsze sprawdzaj wartość null przed podpisaniem. - Długo działające procesy robocze (Octane/RoadRunner/Swoole) współdzielą zablokowany rejestr czcionek. Skonfiguruj
preload_fonts, aby rozgrzanie nastąpiło raz przy starcie procesu roboczego, a nie przy pierwszym żądaniu. - Dla zadania zakończonego niepowodzeniem
failed()jest wywoływane po wyczerpaniutries. Niepowodzenie pojedynczej próby nie wywołujeonFailure, dopóki mechanizm kolejki nie zadeklaruje niepowodzenia terminalnego.
Wydajność
Dział zatytułowany „Wydajność”Synchroniczne generowanie w kontrolerze blokuje żądanie na czas pełnego zbudowania pliku PDF. W przypadku wielostronicowego lub wsadowego wyjścia wyślij GeneratePdfJob i zwróć odpowiedź natychmiast. Rejestry singletonowe rozkładają koszt parsowania czcionek i dekodowania obrazów na cały czas życia procesu roboczego. Koszt przypadający na żądanie ogranicza się wtedy do budowy dokumentu i emisji treści.
Uwagi dotyczące bezpieczeństwa
Dział zatytułowany „Uwagi dotyczące bezpieczeństwa”Kontroler ze wstrzykiwaniem zależności rejestruje klasę wyjątku, a nie jego komunikat ani ślad, aby uniknąć ujawniania wewnętrznych szczegółów w dziennikach. GeneratePdfJob weryfikuje ścieżkę wyjściową w procesie roboczym, aby ograniczyć ryzyko zmanipulowanych zserializowanych ładunków w transporcie kolejki. Pełne omówienie znajdziesz w /integrations/laravel/security-and-operations/.
Zgodność
Dział zatytułowany „Zgodność”| Twierdzenie | Źródło | Klauzula | reference_id |
|---|---|---|---|
| Powiązany identyfikator jest rozwiązywany do zarejestrowanego wpisu | PSR-11 Container | §1.1.2 | |
| Kolejne rozwiązania mogą się różnić w zależności od strategii powiązania (powiązanie fabryczne) | PSR-11 Container | §1.1.2 |
Wskazówki dotyczące rejestrowania w PSR-3 znajdują się w specyfikacji PSR-3. Przypisują one escapowanie symboli zastępczych implementatorowi i wskazują wywołującym, aby przekazywali ustrukturyzowany kontekst. Zobacz dokument psr_3_logger §1.2.
Kontekst komercyjny
Dział zatytułowany „Kontekst komercyjny”Podpisane wyjście PAdES B-B oraz archiwizacja PDF/A przez nextpdf/premium korzystają z tej samej powierzchni wstrzykiwania zależności (DI). To opcjonalna funkcja Enterprise. Udokumentowany tutaj pakiet Core nie wymaga żadnej zmiany kodu, aby z niej skorzystać. Zobacz https://nextpdf.dev/get-license/?intent=laravel-signing.
Zobacz też
Dział zatytułowany „Zobacz też”- /integrations/laravel/quickstart/ — minimalny pierwszy przykład
- /integrations/laravel/configuration/ — klucze kolejki, podpisu i czcionek
- /integrations/laravel/security-and-operations/ — model zagrożeń i utwardzanie
- /integrations/laravel/troubleshooting/ — typowe niepowodzenia produkcyjne