Panduan pengembang Symfony
Sekilas
Bagian berjudul “Sekilas”Bundle Symfony berpusat pada layanan. Injeksikan PdfFactory, panggil create() untuk setiap dokumen Portable Document Format (PDF), dan gunakan builder Messenger untuk pembuatan asinkron. Anda dapat mempertahankan factory sebagai layanan kontainer karena setiap panggilan mengembalikan dokumen baru.
Gunakan panduan ini saat Anda merancang controller, layanan, handler Messenger, atau titik perluasan pada tingkat bundle untuk nextpdf/symfony.
Batasan arsitektur
Bagian berjudul “Batasan arsitektur”| Lapisan | Dimiliki oleh | Tanggung jawab | Jangan letakkan di sini |
|---|---|---|---|
| Controller | Aplikasi | Mengotorisasi permintaan, mengumpulkan input, dan mengembalikan PdfResponse. | Tata letak PDF yang dibagikan antarkasus penggunaan. |
| Layanan aplikasi | Aplikasi | Memuat data domain dan memilih builder. | Logika compiler kontainer Symfony. |
| Layanan builder | Aplikasi | Mengimplementasikan PdfBuilderInterface untuk konstruksi dokumen secara sinkron atau melalui antrean. | Objek permintaan, entity manager, atau konteks yang tidak dapat diserialkan. |
| Bundle Symfony | nextpdf/symfony | Mendaftarkan layanan, pohon konfigurasi, pass perluasan opsional, helper respons, dan objek transfer data (DTO) Messenger. | Kebijakan penyimpanan khusus tenant. |
| Mesin inti | nextpdf/nextpdf | Membuat dan menserialisasi dokumen. | Perilaku respons Symfony atau Messenger. |
Siklus hidup runtime
Bagian berjudul “Siklus hidup runtime”| Tahap | Perilaku | Tindakan pengembang |
|---|---|---|
| Boot bundle | NextPdfBundle::build() mendaftarkan deteksi perluasan opsional. | Biarkan Symfony menemukan bundle atau daftarkan di bundles.php. |
| Pemuatan konfigurasi | NextPdfExtension::load() memproses konfigurasi nextpdf: dan memuat definisi layanan. | Jaga konfigurasi tetap eksplisit dan peka terhadap environment. |
| Penggunaan factory | PdfFactory::create() mengembalikan dokumen baru yang telah dikonfigurasi. | Jangan menyimpan dokumen di dalam layanan. |
| Keluaran controller | PdfResponse mengubah dokumen yang sudah selesai menjadi respons. | Gunakan helper alih-alih menyusun header secara manual. |
| Pengiriman Messenger | GeneratePdfMessage membawa kelas builder, jalur keluaran, dan konteks yang dapat diserialkan. | Jaga konteks tetap minimal dan mudah ditangani sebagai nilai skalar. |
| Penanganan pesan | GeneratePdfHandler menyelesaikan builder dari service locator dan menyimpan dokumen. | Buat builder bersifat deterministik dan idempoten. |
Struktur aplikasi yang direkomendasikan
Bagian berjudul “Struktur aplikasi yang direkomendasikan”| Jalur | Tujuan |
|---|---|
src/Pdf/Builder/* | Layanan yang mengimplementasikan PdfBuilderInterface. |
src/Pdf/Data/* | DTO kecil atau array yang digunakan sebagai konteks builder. |
src/Pdf/Storage/* | Pemilihan akar penyimpanan dan kebijakan nama berkas keluaran. |
src/Controller/* | Titik masuk respons sinkron. |
tests/Pdf/* | Uji builder, respons, Messenger, dan konfigurasi. |
Prioritaskan layanan builder daripada fungsi helper statis. Layanan ini mudah ditandai, didekorasi, diuji, dan digunakan dari Messenger.
<?php
namespace App\Pdf\Builder;
use NextPDF\Core\Document;use NextPDF\Symfony\Message\PdfBuilderInterface;
final readonly class InvoicePdfBuilder implements PdfBuilderInterface{ public function build(Document $document, array $context): Document { $document->setTitle((string) $context['title']) ->addPage() ->writeHtml((string) $context['html']);
return $document; }}Pola respons sinkron
Bagian berjudul “Pola respons sinkron”<?php
namespace App\Controller;
use App\Pdf\Builder\InvoicePdfBuilder;use NextPDF\Symfony\Http\PdfResponse;use NextPDF\Symfony\Service\PdfFactory;
final readonly class InvoiceController{ public function __invoke( PdfFactory $factory, InvoicePdfBuilder $builder, ) { $document = $builder->build($factory->create(), [ 'title' => 'Invoice 1234', 'html' => '<h1>Invoice 1234</h1>', ]);
return PdfResponse::download($document, 'invoice-1234.pdf'); }}Jaga konteks controller tetap kecil. Saat builder membutuhkan banyak objek domain, pindahkan orkestrasi ke dalam layanan aplikasi dan teruskan DTO atau array ternormalisasi ke builder.
Pola Messenger
Bagian berjudul “Pola Messenger”GeneratePdfMessage memvalidasi kelas builder dan jalur keluaran sebelum pengiriman. Handler memvalidasi kembali jalur tersebut saat dijalankan.
<?php
use App\Pdf\Builder\InvoicePdfBuilder;use NextPDF\Symfony\Message\GeneratePdfMessage;
$bus->dispatch(new GeneratePdfMessage( builderClass: InvoicePdfBuilder::class, outputPath: $projectDir . '/var/pdfs/invoice-1234.pdf', builderContext: [ 'title' => 'Invoice 1234', 'html' => '<h1>Invoice 1234</h1>', ],));Jangan memasukkan entitas Doctrine, stream terbuka, closure, objek permintaan, atau objek layanan ke dalam builderContext.
Titik perluasan
Bagian berjudul “Titik perluasan”| Titik perluasan | Gunakan untuk | Batasan |
|---|---|---|
Dekorasi layanan PdfFactory | Menerapkan nilai standar aplikasi sebelum dokumen mencapai controller. | Harus mempertahankan semantik pembuatan dokumen baru. |
PdfBuilderInterface | Mendefinisikan builder dokumen yang diantrekan atau dapat dipakai ulang. | Harus mengembalikan sebuah Document. |
OptionalExtensionPass | Mengaktifkan fitur Artisan atau Premium opsional pada waktu kompilasi. | Ketersediaan ditentukan oleh status saat kompilasi kontainer, bukan status saat permintaan. |
| Pohon konfigurasi Symfony | Nilai standar, PDF/A, pengaturan renderer, tanda tangan, otoritas penandaan waktu (TSA), dan Messenger. | Konfigurasi yang tidak valid sebaiknya gagal saat kontainer dibangun. |
Pengabelan layanan GeneratePdfHandler | Membatasi builder yang dapat dijangkau dari pesan yang diantrekan. | Service locator sebaiknya hanya mengekspos layanan builder yang disetujui. |
Alur kerja pengembangan
Bagian berjudul “Alur kerja pengembangan”- Tambahkan layanan builder dengan input yang deterministik.
- Gunakan
PdfFactory::create()di controller atau layanan. - Tambahkan uji respons untuk nama berkas, jenis konten, dan header.
- Daftarkan builder ke Messenger saat dokumen yang sama harus dihasilkan secara asinkron.
- Tambahkan uji untuk pesan tidak valid pada nama kelas, jalur keluaran, dan bentuk konteks.
- Tambahkan uji kompilasi kontainer dengan konfigurasi minimal dan produksi.
- Ukur waktu render dan memori dengan pengaturan PHP yang sama dengan produksi.
Penanganan kegagalan
Bagian berjudul “Penanganan kegagalan”| Kegagalan | Tempat penanganan yang semestinya | Respons yang direkomendasikan |
|---|---|---|
| Konfigurasi tidak valid | Kompilasi kontainer. | Gagalkan deployment sebelum lalu lintas mencapai aplikasi. |
| Layanan builder tidak ada | Uji handler Messenger serta tag layanan. | Gagalkan pesan dan beri tahu tim pemilik. |
| Jalur keluaran tidak aman | Konstruktor pesan dan kebijakan penyimpanan. | Tolak sebelum pengiriman; pertahankan validasi handler sebagai pertahanan berlapis. |
| Perluasan opsional tidak tersedia | Compiler pass dan perilaku factory. | Nonaktifkan fitur opsional atau jadikan pemasangan eksplisit. |
| Kegagalan konversi layanan atau rendering | Batas builder. | Gagal tertutup kecuali kasus penggunaan memiliki fallback yang terdokumentasi. |
Nilai standar yang aman
Bagian berjudul “Nilai standar yang aman”| Perhatian | Standar | Kapan harus menimpa |
|---|---|---|
| Masa hidup factory | Layanan kontainer. | Pertahankan ini; factory aman karena ia membuat dokumen baru. |
| Masa hidup dokumen | Satu unit kerja. | Jangan pernah membagikannya antarpermintaan atau antarpesan. |
| Validasi jalur keluaran | Konstruktor pesan dan handler. | Tambahkan batasan tenant atau akar penyimpanan di dalam kode aplikasi. |
| Nama berkas respons | document.pdf. | Ganti dengan pengidentifikasi bisnis yang telah disanitasi. |
| Transport Messenger | async. | Gunakan transport khusus ketika pekerjaan PDF berat. |
Daftar periksa pengujian
Bagian berjudul “Daftar periksa pengujian”- Uji kontainer memastikan bundle dikompilasi dengan konfigurasi minimal dan produksi.
- Uji respons memastikan header keamanan dan penanganan nama berkas.
- Uji Messenger memastikan bahwa jalur tidak valid dan nama kelas builder tidak valid gagal sebelum pengiriman.
- Uji handler menggunakan layanan builder sungguhan dan direktori keluaran sementara.
- Uji builder merender dokumen yang representatif dan menyimpannya dengan izin sistem berkas seperti produksi.
- Uji perluasan opsional mencakup kondisi Artisan tidak tersedia, Premium tidak tersedia, dan perilaku profil PDF/A yang dikonfigurasi.