Lewati ke konten
getnextpdf.com

Satu mesin, untuk setiap framework

Spec: PSR-11 Container, §1.1.2Spec: PSR-4 Autoloader, §3

Sebagian besar lanskap PHP yang berkembang pada akhirnya memiliki lebih dari satu framework. NextPDF adalah satu mesin PDF yang menemui masing-masing framework itu dengan caranya sendiri: jembatan idiomatik untuk Laravel, Symfony, dan CodeIgniter, plus jalur standalone untuk kode yang tidak berjalan di satu pun dari mereka. Model dokumennya dibagikan bersama. Hanya cara Anda memanggilnya yang berubah.

Pustaka PDF yang berbeda per tumpukan adalah sebuah pajak yang senyap. Masing- masing memiliki keanehannya sendiri, penanganan fontnya sendiri, gagasannya sendiri tentang apa arti valid. Sebuah invoice yang dirender dengan benar dari layanan Laravel dapat dirender sedikit berbeda dari worker Symfony, karena pustaka yang berbeda menggambarnya. Kini target arsip, penempatan tanda tangan, dan tag aksesibilitas Anda bergantung pada tim mana yang mengirim dokumen itu. Laporan bug berbunyi “PDF-nya salah”, dan jawabannya bergantung pada mesin mana di antara ketiganya yang memproduksinya.

Menstandarkan pada satu mesin meruntuhkan permukaan itu. Ada satu tempat tunggal di mana sebuah profil PDF/A diputuskan, satu alur font untuk disertifikasi, satu validator untuk dipercaya. Framework yang kebetulan Anda gunakan berhenti menjadi variabel dalam menentukan apakah dokumen itu benar.

  • Mesin inti agnostik terhadap framework. nextpdf/core tidak tahu apa pun tentang HTTP, routing, atau perkawatan container. Ia adalah sebuah mesin PDF 2.0 dan tidak lebih dari itu.
  • Setiap jembatan menyesuaikan, ia tidak mengimplementasikan ulang. Paket Laravel, Symfony, dan CodeIgniter memberi Anda sebuah facade atau factory, sebuah helper respons HTTP, dan sebuah jalur generasi antrean atau async — di atas mesin yang sama.
  • Sebuah jembatan mengikuti framework Anda, bukan dokumen Anda. Ia mengubah cara Anda memanggil mesin, tidak pernah apa yang dapat diproduksi mesin.
  • Standalone selalu tersedia. Sebuah alat CLI, sebuah daemon, atau sebuah pustaka tidak memiliki framework untuk dijembatani; ia membangun sebuah dokumen secara langsung.
  • Satu model dokumen berlaku lintas keempatnya. Value object, enum, dan kontrak keluaran yang sama muncul di mana-mana, sehingga sebuah dokumen berpindah antar titik pemanggilan tanpa berubah.

Arsitekturnya adalah pemisahan yang disengaja. Mesin adalah asetnya; jembatan adalah adapter tipis yang berbicara dengan idiom satu framework. Sebuah jembatan mendaftarkan namespace kecil di atas inti yang dibagikan bersama melalui autoloading standar (Spec: PSR-4 Autoloader, §3) dan mengembalikan sebuah dokumen melalui kontrak container (Spec: PSR-11 Container, §1.1.2). Kontrak itu adalah sang pahlawan senyap di sini: ia memungkinkan dua resolusi atas identifier yang sama mengembalikan instance yang berbeda, dan itulah persisnya cara sebuah jembatan memberi Anda dokumen yang segar dan sekali-pakai per permintaan, sambil mempertahankan registri font yang telah diurai dan cache citra sebagai singleton selingkup-proses. Worker berumur-panjang — Octane, RoadRunner, Swoole, Messenger — memperoleh penguraian font yang teramortisasi tanpa kebocoran state lintas-permintaan, secara konstruktif.

Keempat idiom itu hanya berbeda di permukaannya:

  1. Core enginenextpdf/core — the framework-agnostic PDF 2.0 engine; the single shared document model, value objects, and output contract.
  2. Laravel bridgenextpdf/laravel — auto-discovered provider, a Pdf facade, a PdfResponse helper, and a queued GeneratePdfJob.
  3. Symfony bridgenextpdf/symfony — an auto-registered bundle, an injectable PdfFactory, a PdfResponse, and an optional Messenger handler.
  4. CodeIgniter bridgenextpdf/codeigniter — a service and pdf() helper, a Pdf library over a disposable Document, and a PdfResponse.
  5. StandaloneNo framework to bridge from — construct a Document directly in a CLI tool, daemon, or library.
Satu mesin inti yang agnostik terhadap framework dijangkau melalui empat permukaan idiomatik: sebuah facade Laravel, sebuah factory Symfony yang diinjeksikan, sebuah service CodeIgniter, atau sebuah dokumen standalone yang dibangun langsung — masing-masing mengembalikan model Document yang sama dan sekali-pakai.

Baca diagram dari kiri ke kanan dan pelajarannya adalah simetri. Setiap permukaan menyelesaikan ke Document yang sama. Facade Laravel, factory Symfony, service CodeIgniter, dan konstruktor standalone adalah empat pintu menuju satu ruangan.

Tiga baris niat yang sama, diungkapkan dalam setiap idiom. Bagian yang membangun dokumen — halaman, font, sel, penandatanganan, konformitas — identik pada keempatnya, karena ini adalah mesin yang sama.

<?php
declare(strict_types=1);
// Laravel — resolve a fresh document from the container.
use NextPDF\Contracts\PdfDocumentInterface;
$document = app(PdfDocumentInterface::class);
// Symfony — inject the factory, then ask it for a document.
use NextPDF\Symfony\Service\PdfFactory;
$document = $factory->create(); // PdfFactory injected into your service
// CodeIgniter — pull it from the Services layer.
use NextPDF\CodeIgniter\Config\Services;
$document = Services::pdfDocument();
// Standalone — no framework; construct it directly.
use NextPDF\Core\Document;
$document = Document::createStandalone();
// From here, the code is identical regardless of how $document arrived.
$document->addPage();
$document->cell(0, 10, 'One engine, every framework', newLine: true);
$bytes = $document->getPdfData();

Baris-baris pertama adalah satu-satunya perbedaan. Segala sesuatu setelahnya bersifat portabel: pindahkan sebuah layanan pembangun-dokumen dari Symfony ke worker standalone dan kode rendering-nya tidak berubah, karena kontrak yang diandalkannya tidak berubah.

Asumsi yang sering muncul adalah bahwa jembatan framework membuka kemampuan — bahwa validasi tanda tangan jangka panjang atau e-invoicing terstruktur hadir karena Anda memasang nextpdf/laravel alih-alih memanggil mesin secara langsung. Tidak demikian. Sebuah jembatan mengubah titik pemanggilan, tidak pernah jangkauan mesin. Kemampuan inti seperti keluaran PDF/A dan penandatanganan baseline PAdES bersifat sumber terbuka dan menjangkau setiap permukaan; kemampuan lanjutan dibuka oleh sebuah edisi dan kemudian tersedia melalui jembatan mana pun atau jalur standalone secara setara. Memilih sebuah integrasi framework bukanlah memilih sebuah himpunan fitur.

Kesalahpahaman cerminnya adalah bahwa “satu mesin” mesti berarti satu jalur rendering untuk setiap dokumen. Tidak demikian. Mesin in-process merender PDF secara langsung; ketika sebuah dokumen benar-benar membutuhkan mesin tata letak sekelas-peramban, sebuah paket renderer menanganinya. Rendering dan pemanggilan adalah sumbu yang terpisah — panduan keputusan integrasi adalah tempat yang memetakannya.

Sebuah jembatan tidak memperluas apa yang dapat dirender mesin. Itu adalah batas yang jujur, dan itulah intinya: kemampuan berada di inti dan di tingkat, bukan di adapter yang Anda gunakan untuk menjangkaunya.

Framework bridges over one engine — edition availability
EditionAvailability
Core

Setiap jembatan (Laravel, Symfony, CodeIgniter) dan jalur standalone berlisensi Apache-2.0 dan bekerja terhadap Core. Mereka menyesuaikan atau mengekspos mesin; mereka tidak menggerbangi fitur dan tidak mengubah apa yang dapat diproduksinya.

Pro

Kemampuan lanjutan seperti validasi tanda tangan jangka panjang (PAdES B-LT dan B-LTA) dibuka oleh sebuah edisi, lalu dijangkau secara identik melalui jembatan mana pun atau standalone — tidak pernah dengan berganti framework. Keluaran arsip PDF/A dan penandatanganan baseline PAdES (B-B dan B-T) sudah ada di Core, tersedia dengan cara yang sama melalui setiap permukaan.

Enterprise

E-invoicing terstruktur (EN 16931) dan perkakas kepatuhan yang lebih dalam juga merupakan kemampuan edisi, demikian pula sama saja permukaan mana pun yang memanggil mesin, sementara validasi konformitas itu sendiri dikirim di dalam Core.

Dua batas lebih lanjut layak dinyatakan secara gamblang. Pertama, setiap jembatan mengikuti versi mayor terkini dari framework-nya — Laravel, Symfony, dan CodeIgniter masing-masing menyematkan rentang yang didukung, sehingga “setiap framework” berarti versi yang didukung dari masing-masing, bukan setiap rilis historis; perlakukan dokumentasi setiap paket sendiri sebagai otoritatif untuk API-nya. Kedua, jembatan-jembatan itu adalah adapter framework, bukan backend rendering. Jika sebuah dokumen membutuhkan mesin tata letak peramban penuh, itu adalah pilihan renderer yang independen dari framework mana yang memanggil mesin.

  • Panduan keputusan integrasi — peta kasus-penggunaan-ke-paket, termasuk renderer dan permukaan layanan Connect, ketika Anda perlu memutuskan alih-alih menstandarkan.
  • Open core, tanpa lock-in — mengapa mesin adalah asetnya dan jembatannya tipis, sehingga menstandarkan tidak menjerat Anda.
  • Alur HTML — apa yang dicakup mesin in-process, sehingga Anda tahu kapan sebuah renderer peramban menjadi pertanyaan terpisah.
  • Fondasi PHP 8.4 — batas bawah runtime yang dibagikan bersama oleh setiap jembatan dan jalur standalone.
  • Mesin intinextpdf/core, mesin PDF 2.0 yang agnostik terhadap framework yang menjadi pondasi setiap jembatan dan jalur standalone.
  • Jembatan framework — sebuah paket integrasi (Laravel, Symfony, CodeIgniter) yang menyesuaikan mesin dengan idiom sebuah framework — facade, factory, respons, queued job — tanpa mengubah kemampuannya.
  • Jalur standalone — menggunakan mesin inti secara langsung, tanpa framework, dengan membangun sebuah Document sendiri; rute untuk alat CLI, daemon, dan pustaka.
  • Dokumen sekali-pakai — kontrak Document yang dipakai sekali: bangun, pancarkan, buang. Setiap resolusi container mengembalikan satu yang segar, sehingga tidak ada state yang bocor antar permintaan dalam worker berumur-panjang.
  • PAdES — PDF Advanced Electronic Signatures, keluarga profil ETSI untuk penandatanganan PDF. Penandatanganan baseline (B-B dan B-T) ada di Core; validasi jangka panjang (B-LT dan B-LTA) adalah kemampuan edisi lanjutan. Keduanya dijangkau melalui permukaan mana pun, dibahas mendalam pada halaman penandatanganan.