Jeden silnik, każdy framework
Spec: PSR-11 Container, §1.1.2PSR-11 Container §1.1.2Spec: PSR-4 Autoloader, §3PSR-4 Autoloader §3
W skrócie
Dział zatytułowany „W skrócie”Większość rosnących środowisk PHP kończy z więcej niż jednym frameworkiem. NextPDF to jeden silnik PDF, który spotyka się z każdym z nich na jego własnych warunkach: idiomatyczne mostki dla Laravela, Symfony i CodeIgnitera oraz ścieżka samodzielna dla kodu, który nie działa w żadnym z nich. Model dokumentu jest współdzielony. Zmienia się tylko sposób, w jaki go wywołujesz.
Dlaczego to ma znaczenie
Dział zatytułowany „Dlaczego to ma znaczenie”Inna biblioteka PDF dla każdego stosu to cichy podatek. Każda ma swoje osobliwości, swoją obsługę czcionek, swoje wyobrażenie o tym, co znaczy prawidłowy. Faktura, która renderuje się poprawnie z usługi Laravela, może renderować się subtelnie inaczej z procesu roboczego Symfony, bo narysowała ją inna biblioteka. Teraz twój cel archiwalny, rozmieszczenie podpisu i znaczniki dostępności zależą od tego, który zespół wysłał dokument. Zgłoszenie błędu mówi „PDF jest zły”, a odpowiedź zależy od tego, który z trzech silników go wytworzył.
Standaryzacja na jednym silniku zwija tę powierzchnię. Istnieje jedno miejsce, w którym ustala się profil PDF/A, jeden potok czcionek do certyfikacji, jeden walidator, któremu się ufa. Framework, w którym akurat jesteś, przestaje być zmienną w tym, czy dokument jest poprawny.
Wersja skrócona
Dział zatytułowany „Wersja skrócona”- Silnik rdzeniowy jest niezależny od frameworka.
nextpdf/corenie wie nic o HTTP, routingu ani podłączaniu kontenera. To silnik PDF 2.0 i nic więcej. - Każdy mostek adaptuje, nie reimplementuje. Pakiety Laravela, Symfony i CodeIgnitera dają ci fasadę lub fabrykę, pomocnika odpowiedzi HTTP oraz ścieżkę generowania w kolejce lub asynchronicznego — nad tym samym silnikiem.
- Mostek podąża za twoim frameworkiem, nie za twoim dokumentem. Zmienia sposób, w jaki wywołujesz silnik, nigdy zaś to, co silnik potrafi wytworzyć.
- Tryb samodzielny jest zawsze dostępny. Narzędzie CLI, demon lub biblioteka nie ma frameworka, z którego można by mostkować; konstruuje dokument bezpośrednio.
- Jeden model dokumentu przemieszcza się po wszystkich czterech. Te same obiekty wartości, typy wyliczeniowe i kontrakt wyjścia pojawiają się wszędzie, więc dokument przenosi się między miejscami wywołania bez zmian.
Jak podchodzi do tego NextPDF
Dział zatytułowany „Jak podchodzi do tego NextPDF”Architektura to celowy podział. Silnik to zasób; mostek to cienki adapter, który mówi idiomami jednego frameworka. Mostek rejestruje małą przestrzeń nazw nad współdzielonym rdzeniem poprzez standardowy autoloading (Spec: PSR-4 Autoloader, §3PSR-4 Autoloader §3) i zwraca dokument poprzez kontrakt kontenera (Spec: PSR-11 Container, §1.1.2PSR-11 Container §1.1.2). Ten kontrakt jest tutaj cichym bohaterem: pozwala dwóm rozwiązaniom tego samego identyfikatora zwrócić różne instancje, i właśnie tak mostek daje ci świeży, jednorazowy dokument na żądanie, jednocześnie utrzymując sparsowany rejestr czcionek oraz pamięć podręczną obrazów jako singletony obejmujące cały proces. Długo żyjące procesy robocze — Octane, RoadRunner, Swoole, Messenger — otrzymują zamortyzowane parsowanie czcionek bez wycieku stanu między żądaniami, z samej konstrukcji.
Te cztery idiomy różnią się tylko na powierzchni:
- Core enginenextpdf/core — the framework-agnostic PDF 2.0 engine; the single shared document model, value objects, and output contract.
- Laravel bridgenextpdf/laravel — auto-discovered provider, a Pdf facade, a PdfResponse helper, and a queued GeneratePdfJob.
- Symfony bridgenextpdf/symfony — an auto-registered bundle, an injectable PdfFactory, a PdfResponse, and an optional Messenger handler.
- CodeIgniter bridgenextpdf/codeigniter — a service and pdf() helper, a Pdf library over a disposable Document, and a PdfResponse.
- StandaloneNo framework to bridge from — construct a Document directly in a CLI tool, daemon, or library.
Przeczytaj diagram od lewej do prawej, a lekcją jest symetria. Każda
powierzchnia rozwiązuje się do tego samego Document. Fasada Laravela, fabryka
Symfony, usługa CodeIgnitera oraz samodzielny konstruktor to czworo drzwi do
jednego pokoju.
Przykład praktyczny
Dział zatytułowany „Przykład praktyczny”Te same trzy wiersze intencji, wyrażone w każdym idiomie. Ciało, które buduje dokument — strony, czcionki, komórki, podpisywanie, zgodność — jest identyczne we wszystkich czterech, bo to ten sam silnik.
<?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();Pierwsze wiersze to jedyna różnica. Wszystko po nich jest przenośne: przenieś usługę budującą dokument z Symfony do samodzielnego procesu roboczego, a kod renderujący się nie zmieni, bo kontrakt, od którego zależy, się nie zmienił.
Częste nieporozumienie
Dział zatytułowany „Częste nieporozumienie”Częste założenie jest takie, że mostek frameworka odblokowuje możliwości — że
walidacja długoterminowa podpisu lub ustrukturyzowane e-fakturowanie pojawia
się, bo zainstalowałeś nextpdf/laravel, zamiast wywoływać silnik bezpośrednio.
Tak nie jest. Mostek zmienia miejsce wywołania, nigdy zasięg silnika.
Możliwości rdzeniowe, takie jak wyjście PDF/A oraz podpisywanie bazowe PAdES,
są otwartoźródłowe i sięgają każdej powierzchni; zaawansowane możliwości są
odblokowywane przez edycję i wówczas są dostępne poprzez dowolny mostek lub
ścieżkę samodzielną na równi. Wybór integracji frameworka to nie wybór zestawu
funkcji.
Lustrzanym nieporozumieniem jest to, że „jeden silnik” musi oznaczać jedną ścieżkę renderowania dla każdego dokumentu. Nie musi. Silnik wewnątrzprocesowy renderuje PDF bezpośrednio; gdy dokument naprawdę potrzebuje silnika układu klasy przeglądarkowej, obsługuje to pakiet renderera. Renderowanie i wywoływanie to osobne osie — przewodnik decyzji o integracji jest miejscem, które je mapuje.
Ograniczenia i granice
Dział zatytułowany „Ograniczenia i granice”Mostek nie rozszerza tego, co silnik potrafi wyrenderować. To uczciwe ograniczenie i o to chodzi: możliwość żyje w rdzeniu i warstwie, a nie w adapterze, przez który do niej sięgasz.
| Edition | Availability |
|---|---|
| Core | Every bridge (Laravel, Symfony, CodeIgniter) and the standalone path are Apache-2.0 and work against Core. They adapt or expose the engine; they do not gate features and do not change what it can produce. |
| Pro | Advanced capabilities such as long-term signature validation (PAdES B-LT and B-LTA) are unlocked by an edition, then reached identically through any bridge or standalone — never by switching framework. PDF/A archival output and PAdES baseline signing (B-B and B-T) are already in Core, available the same way through every surface. |
| Enterprise | Structured e-invoicing (EN 16931) and deeper compliance tooling are edition capabilities too, likewise the same whichever surface calls the engine, while conformance validation itself ships in Core. |
Dwie kolejne granice warto wyłożyć wprost. Po pierwsze, każdy mostek śledzi bieżącą wersję główną swojego frameworka — Laravel, Symfony i CodeIgniter każdy przypina wspierany zakres, więc „każdy framework” oznacza wspieraną wersję każdego z nich, a nie każde historyczne wydanie; traktuj dokumentację każdego pakietu jako miarodajną dla jego API. Po drugie, mostki to adaptery frameworków, a nie zaplecza renderujące. Jeśli dokument potrzebuje pełnego silnika układu przeglądarkowego, to jest to wybór renderera niezależny od tego, który framework wywołał silnik.
Powiązane dokumenty
Dział zatytułowany „Powiązane dokumenty”- Przewodnik decyzji o integracji — mapa przypadek-użycia-do-pakietu, w tym renderery oraz powierzchnia usługi Connect, gdy musisz zdecydować, zamiast standaryzować.
- Otwarty rdzeń, brak uzależnienia od dostawcy — dlaczego silnik to zasób, a mostki są cienkie, więc standaryzacja cię nie uwięzi.
- Potok HTML — co obejmuje silnik wewnątrzprocesowy, byś wiedział, kiedy renderer przeglądarkowy jest osobnym pytaniem.
- Fundamenty PHP 8.4 — minimalny próg środowiska uruchomieniowego, który dzieli każdy mostek i ścieżka samodzielna.
Słowniczek
Dział zatytułowany „Słowniczek”- Silnik rdzeniowy —
nextpdf/core, niezależny od frameworka silnik PDF 2.0, na którym budują każdy mostek i ścieżka samodzielna. - Mostek frameworka — pakiet integracyjny (Laravel, Symfony, CodeIgniter), który adaptuje silnik do idiomów frameworka — fasada, fabryka, odpowiedź, zadanie w kolejce — bez zmiany jego możliwości.
- Ścieżka samodzielna — używanie silnika rdzeniowego bezpośrednio, bez
frameworka, przez samodzielne skonstruowanie
Document; trasa dla narzędzi CLI, demonów i bibliotek. - Dokument jednorazowy — kontrakt
Documentdo jednorazowego użycia: zbuduj, wyemituj, odrzuć. Każde rozwiązanie kontenera zwraca świeży, więc żaden stan nie wycieka między żądaniami w długo żyjącym procesie roboczym. - PAdES — PDF Advanced Electronic Signatures, rodzina profili ETSI do podpisywania PDF. Podpisywanie bazowe (B-B i B-T) jest w Core; walidacja długoterminowa (B-LT i B-LTA) to możliwość zaawansowanej edycji. Do każdego sięga się przez dowolną powierzchnię, co dokładnie omawiają strony o podpisywaniu.