Penggunaan produksi pada CodeIgniter 4
Sekilas pandang
Bagian berjudul “Sekilas pandang”Controller produksi menerima layanan NextPDF konkret. Controller tersebut menangani hierarki eksepsi yang terdokumentasi secara eksplisit dan memancarkan sinyal observabilitas. Pindahkan pekerjaan Portable Document Format (PDF) yang berjalan lama ke luar alur permintaan melalui CodeIgniter 4 Queue.
Gambaran konseptual
Bagian berjudul “Gambaran konseptual”CodeIgniter 4 menyelesaikan (resolve) layanan paket ini melalui locator-nya. Dalam pola service-locator, sebuah objek menerima container dan menggunakannya untuk mengambil dependensinya sendiri. Panduan PHP Standard Recommendation (PSR) tidak menganjurkan pola tersebut (PSR-11 §1.3, modal SHOULD NOT). Untuk mengikuti panduan itu, selesaikan setiap layanan NextPDF satu kali pada batas controller, lalu teruskan objek konkretnya ke lapisan di dalamnya. Jangan teruskan kelas Services atau container ke kode domain Anda.
Setiap contoh PHP menempatkan declare(strict_types=1); pada barisnya sendiri (PSR-12 §x1.x3.p34).
Permukaan API
Bagian berjudul “Permukaan API”| Aspek produksi | Permukaan terverifikasi |
|---|---|
| Menyelesaikan layanan | Services::pdf(false), Services::pdfDocument(false), Services::documentFactory() |
| Membangun respons | PdfResponse::download() / inline() → DownloadResponse |
| Menangkap kegagalan | NextPDF\Exception\NextPdfException (tipe dasar ekosistem) |
| Pembuatan asinkron | GeneratePdfJob terdaftar di Config\Queue::$jobHandlers |
| Penjaga path / callable | GeneratePdfJob melempar InvalidArgumentException |
Controller produksi — penanganan error dan observabilitas
Bagian berjudul “Controller produksi — penanganan error dan observabilitas”Semua eksepsi yang dilempar engine inti merupakan turunan dari NextPDF\Exception\NextPdfException. Tangkap satu tipe ini saja untuk mencakup kegagalan inti maupun ekstensi. Blok catch ini mencatat konteks dan mengembalikan respons error yang terdefinisi, bukan catch kosong.
<?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]); } }}Services::pdf(false) mengembalikan library baru beserta dokumen dasar baru setiap kali dipanggil. Permintaan yang berjalan bersamaan tidak pernah berbagi state dokumen. Pengujian fungsional paket ini menegaskan perilaku tersebut.
Masa hidup layanan yang aman untuk worker
Bagian berjudul “Masa hidup layanan yang aman untuk worker”Registry font dan gambar dirancang sebagai singleton yang hidup selama proses berjalan. Registry font melakukan pemanasan dan penguncian satu kali. Registry gambar adalah cache least recently used (LRU) yang dibatasi. Pada worker yang berjalan lama (server spark CodeIgniter, runner bergaya RoadRunner, atau worker antrean), hal ini disengaja: registry yang biaya pembuatannya mahal tetap bertahan, sementara setiap dokumen selalu baru. Jangan meminta dokumen bersama (Services::pdfDocument(true)) di dalam kode permintaan atau job; dokumen tersebut hanya ada untuk reset pengujian dan akan berbagi konten lintas permintaan.
Pembuatan asinkron dengan CodeIgniter Queue
Bagian berjudul “Pembuatan asinkron dengan CodeIgniter Queue”GeneratePdfJob menjalankan pembuatan PDF di luar alur permintaan melalui codeigniter4/queue. Runtime antrean memerlukan dua pengaturan. Konfigurasikan keduanya dengan benar.
1. Daftarkan handler job berdasarkan nama
Bagian berjudul “1. Daftarkan handler job berdasarkan nama”Antrean menyelesaikan sebuah job berdasarkan kunci nama, bukan berdasarkan string kelas. Handler antrean memvalidasi nama job yang dikirimkan terhadap kunci-kunci pada Config\Queue::$jobHandlers. Handler menolak nama yang tidak dikenal dengan CodeIgniter\Queue\Exceptions\QueueException. Daftarkan job tersebut di 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, ];}2. Kirim berdasarkan nama yang terdaftar
Bagian berjudul “2. Kirim berdasarkan nama yang terdaftar”Kirim job dengan nama yang terdaftar sebagai argumen kedua. Argumen pertama adalah nama antrean. Argumen ketiga adalah array data job.
<?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. Implementasikan builder di bawah App\PdfBuilders
Bagian berjudul “3. Implementasikan builder di bawah App\PdfBuilders”Job hanya mengizinkan callable builder di dalam namespace App\PdfBuilders dan membatasi path keluaran ke WRITEPATH/pdfs/. Implementasikan builder sebagai method statis. Builder menerima Document baru dan array konteks, lalu mengembalikan dokumen tersebut.
<?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; }}Jalankan worker
Bagian berjudul “Jalankan worker”php spark queue:work pdf-queueSetiap eksekusi job dimulai dengan dokumen baru dari Services::pdfDocument(). Job menerapkan builder, lalu menyimpannya ke path yang telah divalidasi. Pengujian paket ini memverifikasi bahwa dua eksekusi job berurutan tidak berbagi state dokumen.
Kasus tepi & jebakan
Bagian berjudul “Kasus tepi & jebakan”- Antrean menolak
GeneratePdfJob::classsebagai nama job saat dikirimkan karena itu bukan kunci yang terdaftar'generate-pdf'. Selalu gunakan kuncijobHandlerssaat mengirim job. - String builder harus sama persis dengan
App\PdfBuilders\<Class>::<method>. Fungsi, namespace lain, atau payload dengan awalan maupun akhiran tambahan akan memunculkanInvalidArgumentExceptionsebelum kode apa pun berjalan. - Path keluaran harus mengarah ke dalam
WRITEPATH/pdfs/dan berakhiran.pdf(tidak peka huruf besar/kecil). Path traversal dan path dengan awalan sibling akan ditolak. codeigniter4/queueadalah dependensi paket yang hanya untuk pengembangan. Jadikan dependensi itu wajib pada aplikasi yang menjalankan worker.
Performa
Bagian berjudul “Performa”Registry dibuat satu kali per proses worker. Biaya pembuatan dokumen berskala sesuai konten, bukan adapter. Untuk job batch berukuran besar, gunakan jalur antrean agar worker yang melayani permintaan tetap responsif. Tetapkan performance_budget pada setiap resep yang memiliki target terukur.
Catatan keamanan
Bagian berjudul “Catatan keamanan”Job antrean adalah permukaan dengan risiko tertinggi. Ketika broker dapat dijangkau, payload antrean dapat dipengaruhi oleh penyerang. Allowlist callable dan pembatasan path dibahas di /integrations/codeigniter/security-and-operations/ bersama kasus penolakan yang terverifikasi.
Kesesuaian
Bagian berjudul “Kesesuaian”- Controller menerima layanan konkret, bukan container, sesuai dengan panduan service-locator PSR-11 §1.3.
Konteks komersial
Bagian berjudul “Konteks komersial”Inti NextPDF berlisensi Apache-2.0. Untuk menghasilkan keluaran bertanda tangan dan PDF/A di dalam job antrean, pasang NextPDF Pro atau Enterprise di lingkungan worker. Paket CodeIgniter mengekspos method layanan yang sesuai. Method tersebut mengembalikan null hingga paket Premium yang sesuai dipasang. Lihat </get-license/?intent=codeigniter-async-signing>.
Lihat juga
Bagian berjudul “Lihat juga”- /integrations/codeigniter/quickstart/ — versi minimal dari controller di halaman ini.
- /integrations/codeigniter/configuration/ — penandatanganan, Time Stamping Authority (TSA), dan konfigurasi path.
- /integrations/codeigniter/security-and-operations/ — model ancaman antrean dan pengerasan keamanan.
- /integrations/codeigniter/troubleshooting/ — mode kegagalan antrean dan discovery.
- /integrations/codeigniter/integration/ — referensi penyambungan (wiring) dan smoke test.