Przejdź do głównej zawartości

Użycie produkcyjne w CodeIgniter 4

Kontrolery produkcyjne otrzymują konkretne usługi NextPDF. Jawnie obsługują udokumentowaną hierarchię wyjątków i emitują sygnały obserwowalności. Przenieś długotrwałe operacje dotyczące formatu Portable Document Format (PDF) poza obsługę żądania, korzystając z kolejki CodeIgniter 4 Queue.

CodeIgniter 4 rozwiązuje usługi pakietu za pomocą własnego lokatora. We wzorcu service locator obiekt otrzymuje kontener i używa go do pobierania własnych zależności. Wytyczne PHP Standard Recommendation (PSR) odradzają ten wzorzec (PSR-11 §1.3, czasownik modalny SHOULD NOT). Aby zastosować się do tych wytycznych, rozwiąż każdą usługę NextPDF jednokrotnie na granicy kontrolera, a następnie przekaż dalej konkretny obiekt. Nie przekazuj klasy Services ani kontenera do kodu domeny.

W każdym przykładzie PHP declare(strict_types=1); znajduje się w osobnym wierszu (PSR-12 §x1.x3.p34).

Zagadnienie produkcyjneZweryfikowana powierzchnia
Rozwiązywanie usługServices::pdf(false), Services::pdfDocument(false), Services::documentFactory()
Budowanie odpowiedziPdfResponse::download() / inline()DownloadResponse
Przechwytywanie błędówNextPDF\Exception\NextPdfException (typ bazowy ekosystemu)
Generowanie asynchroniczneGeneratePdfJob zarejestrowane w Config\Queue::$jobHandlers
Zabezpieczenia ścieżek / wywoływalnychGeneratePdfJob zgłasza InvalidArgumentException

Kontroler produkcyjny — obsługa błędów i obserwowalność

Dział zatytułowany „Kontroler produkcyjny — obsługa błędów i obserwowalność”

Wszystkie wyjątki zgłaszane przez silnik podstawowy rozszerzają NextPDF\Exception\NextPdfException. Przechwyć ten jeden typ, aby objąć błędy rdzenia i rozszerzeń. Ten blok catch rejestruje kontekst i zwraca zdefiniowaną odpowiedź błędu; nigdy nie jest pusty.

<?php
declare(strict_types=1);
namespace App\Controllers;
use CodeIgniter\HTTP\DownloadResponse;
use CodeIgniter\HTTP\ResponseInterface;
use NextPDF\CodeIgniter\Config\Services;
use NextPDF\Exception\NextPdfException;
use Psr\Log\LoggerInterface;
final class InvoiceController extends BaseController
{
public function download(int $id): DownloadResponse|ResponseInterface
{
/** @var LoggerInterface $logger */
$logger = \service('logger');
$start = \hrtime(true);
try {
$pdf = Services::pdf(false);
$pdf->document()->addPage();
$pdf->document()->cell(0, 10, "Invoice #{$id}");
$response = $pdf->download("invoice-{$id}.pdf");
$logger->info('pdf.invoice.generated', [
'invoice_id' => $id,
'elapsed_ms' => (\hrtime(true) - $start) / 1_000_000,
]);
return $response;
} catch (NextPdfException $e) {
$logger->error('pdf.invoice.failed', [
'invoice_id' => $id,
'exception' => $e::class,
'message' => $e->getMessage(),
]);
return $this->response
->setStatusCode(ResponseInterface::HTTP_INTERNAL_SERVER_ERROR)
->setJSON(['error' => 'pdf_generation_failed', 'invoice_id' => $id]);
}
}
}

Przy każdym wywołaniu Services::pdf(false) zwraca nową instancję biblioteki i nowy dokument bazowy. Współbieżne żądania nigdy nie współdzielą stanu dokumentu. Testy funkcjonalne pakietu potwierdzają to zachowanie.

Cykle życia usług bezpieczne dla procesów roboczych

Dział zatytułowany „Cykle życia usług bezpieczne dla procesów roboczych”

Rejestry czcionek i obrazów są z założenia singletonami o cyklu życia procesu. Rejestr czcionek jest rozgrzewany i blokowany jednorazowo. Rejestr obrazów to ograniczona pamięć podręczna typu least recently used (LRU). W długo działającym procesie roboczym (serwer CodeIgniter spark, mechanizm uruchomieniowy w stylu RoadRunner lub proces roboczy kolejki) jest to zamierzone: kosztowne rejestry pozostają w pamięci, podczas gdy każdy dokument jest nowy. Nie pobieraj współdzielonego dokumentu (Services::pdfDocument(true)) w kodzie żądania ani zadania; służy on wyłącznie do resetowania testów i powodowałby współdzielenie zawartości między żądaniami.

GeneratePdfJob uruchamia generowanie PDF poza obsługą żądania za pomocą codeigniter4/queue. Środowisko uruchomieniowe kolejki wymaga dwóch elementów konfiguracji. Skonfiguruj oba poprawnie.

1. Zarejestruj procedurę obsługi zadania według nazwy

Dział zatytułowany „1. Zarejestruj procedurę obsługi zadania według nazwy”

Kolejka rozwiązuje zadanie według klucza nazwy, a nie według ciągu znaków klasy. Procedura obsługi kolejki porównuje nazwę dodawanego zadania z kluczami Config\Queue::$jobHandlers. Odrzuca nieznaną nazwę, zgłaszając CodeIgniter\Queue\Exceptions\QueueException. Zarejestruj zadanie w pliku app/Config/Queue.php:

<?php
declare(strict_types=1);
namespace Config;
use CodeIgniter\Queue\Config\Queue as BaseQueue;
use NextPDF\CodeIgniter\Jobs\GeneratePdfJob;
final class Queue extends BaseQueue
{
/** @var array<string, class-string> */
public array $jobHandlers = [
'generate-pdf' => GeneratePdfJob::class,
];
}

Dodaj zadanie do kolejki, podając zarejestrowaną nazwę jako drugi argument. Pierwszy argument to nazwa kolejki. Trzeci argument to tablica danych zadania.

<?php
declare(strict_types=1);
namespace App\Controllers;
use CodeIgniter\HTTP\ResponseInterface;
final class InvoiceController extends BaseController
{
public function queueInvoice(int $id): ResponseInterface
{
\service('queue')->push('pdf-queue', 'generate-pdf', [
'builder' => 'App\\PdfBuilders\\InvoiceBuilder::build',
'outputPath' => WRITEPATH . 'pdfs/invoice-' . $id . '.pdf',
'context' => ['invoice_id' => $id],
]);
return $this->response
->setStatusCode(ResponseInterface::HTTP_ACCEPTED)
->setJSON(['status' => 'queued', 'invoice_id' => $id]);
}
}

3. Zaimplementuj builder w przestrzeni nazw App\PdfBuilders

Dział zatytułowany „3. Zaimplementuj builder w przestrzeni nazw App\PdfBuilders”

Zadanie dopuszcza wywoływalne buildery tylko w przestrzeni nazw App\PdfBuilders i ogranicza ścieżki wyjściowe do WRITEPATH/pdfs/. Zaimplementuj builder jako metodę statyczną. Builder otrzymuje nowy obiekt Document oraz tablicę kontekstu, a następnie zwraca dokument.

<?php
declare(strict_types=1);
namespace App\PdfBuilders;
use NextPDF\Core\Document;
final class InvoiceBuilder
{
/** @param array<string, mixed> $context */
public static function build(Document $document, array $context): Document
{
$invoiceId = (int) ($context['invoice_id'] ?? 0);
$document->addPage();
$document->cell(0, 10, "Invoice #{$invoiceId}");
return $document;
}
}
Okno terminala
php spark queue:work pdf-queue

Każde uruchomienie zadania rozpoczyna się od nowego dokumentu z Services::pdfDocument(). Zadanie stosuje builder, a następnie zapisuje wynik do zweryfikowanej ścieżki. Testy pakietu weryfikują, że dwa kolejne uruchomienia zadania nie współdzielą stanu dokumentu.

  • Kolejka odrzuca GeneratePdfJob::class jako nazwę zadania podczas dodawania, ponieważ nie jest to zarejestrowany klucz 'generate-pdf'. Zawsze używaj klucza z jobHandlers.
  • Ciąg znaków buildera musi dokładnie pasować do App\PdfBuilders\<Class>::<method>. Funkcje, inne przestrzenie nazw lub ładunki z przedrostkiem albo przyrostkiem powodują zgłoszenie InvalidArgumentException, zanim wykona się jakikolwiek kod.
  • Ścieżka wyjściowa musi rozwiązywać się wewnątrz WRITEPATH/pdfs/ i kończyć się rozszerzeniem .pdf (bez rozróżniania wielkości liter). Ścieżki z przechodzeniem katalogów oraz z prefiksem katalogu siostrzanego są odrzucane.
  • codeigniter4/queue jest w pakiecie zależnością wyłącznie deweloperską. Dołącz ją w aplikacji, która uruchamia procesy robocze.

Rejestry są tworzone raz na proces roboczy. Koszt budowania dokumentu skaluje się wraz z zawartością, a nie z adapterem. W przypadku dużych zadań wsadowych użyj kolejki, aby procesy robocze obsługujące żądania pozostawały responsywne. Ustaw performance_budget dla każdego przepisu z mierzalnym celem.

Zadanie w kolejce jest powierzchnią o najwyższym ryzyku. Gdy broker jest dostępny, atakujący może kształtować ładunki kolejki. Lista dozwolonych wywoływalnych oraz ograniczanie ścieżek są omówione w /integrations/codeigniter/security-and-operations/ wraz ze zweryfikowanymi przypadkami odrzucenia.

  • Kontrolery otrzymują konkretne usługi, a nie kontener, zgodnie z wytycznymi PSR-11 §1.3 dotyczącymi wzorca service locator.

Rdzeń NextPDF jest na licencji Apache-2.0. Aby w zadaniach kolejki tworzyć podpisane wyniki oraz wyniki w formacie PDF/A, zainstaluj NextPDF Pro lub Enterprise w środowisku procesu roboczego. Pakiet CodeIgniter udostępnia odpowiadające metody usług. Zwracają null, dopóki nie zostanie zainstalowany odpowiedni pakiet Premium. Zobacz </get-license/?intent=codeigniter-async-signing>.

  • /integrations/codeigniter/quickstart/ — minimalna wersja tych kontrolerów.
  • /integrations/codeigniter/configuration/ — podpisywanie, urząd znakowania czasem (TSA) oraz konfiguracja ścieżek.
  • /integrations/codeigniter/security-and-operations/ — model zagrożeń kolejki i utwardzanie zabezpieczeń.
  • /integrations/codeigniter/troubleshooting/ — tryby awarii kolejki i ich wykrywanie.
  • /integrations/codeigniter/integration/ — odniesienie do połączeń oraz test dymny.