Один движок, любой фреймворк
Spec: PSR-11 Container, §1.1.2PSR-11 Container §1.1.2Spec: PSR-4 Autoloader, §3PSR-4 Autoloader §3
Большинство растущих PHP-хозяйств в итоге обзаводятся не одним фреймворком. NextPDF — это один движок PDF, который встречает каждый из них на его собственных условиях: идиоматичные мосты для Laravel, Symfony и CodeIgniter плюс самостоятельный путь для кода, который не работает ни в одном из них. Модель документа общая. Меняется только то, как вы её вызываете.
Почему это важно
Заголовок раздела «Почему это важно»Отдельная библиотека PDF под каждый стек — тихий налог. У каждой свои причуды, своя обработка шрифтов, своё представление о том, что значит “корректный”. Счёт, который правильно отрисовывается из сервиса Laravel, может отрисоваться чуть иначе из воркера Symfony, потому что его рисовала другая библиотека. Теперь ваша архивная цель, размещение подписи и теги доступности зависят от того, какая команда выпустила документ. В отчёте об ошибке сказано “PDF неправильный”, и ответ зависит от того, какой из трёх движков его создал.
Стандартизация на одном движке схлопывает эту поверхность. Есть единственное место, где решается профиль PDF/A, один конвейер шрифтов, который надо сертифицировать, одно средство проверки, которому надо доверять. Фреймворк, в котором вы случайно оказались, перестаёт быть переменной в вопросе, корректен ли документ.
Если коротко
Заголовок раздела «Если коротко»- Движок ядра не зависит от фреймворка.
nextpdf/coreничего не знает об HTTP, маршрутизации или связывании контейнера. Это движок PDF 2.0 и ничего более. - Каждый мост адаптирует, а не переписывает. Пакеты Laravel, Symfony и CodeIgniter дают вам фасад или фабрику, помощник для HTTP-ответа и путь генерации в очереди или асинхронно — поверх того же движка.
- Мост следует за вашим фреймворком, а не за вашим документом. Он меняет то, как вы вызываете движок, и никогда — то, что движок может создать.
- Самостоятельный путь доступен всегда. У инструмента CLI, демона или библиотеки нет фреймворка, от которого можно строить мост; они конструируют документ напрямую.
- Одна модель документа путешествует по всем четырём. Одни и те же объекты-значения, перечисления и контракт вывода появляются везде, поэтому документ перемещается между местами вызова без изменений.
Как это реализовано в NextPDF
Заголовок раздела «Как это реализовано в NextPDF»Архитектура — это намеренное разделение. Движок — это актив; мост — тонкий адаптер, который говорит на идиомах одного фреймворка. Мост регистрирует небольшое пространство имён поверх общего ядра через стандартную автозагрузку (Spec: PSR-4 Autoloader, §3PSR-4 Autoloader §3) и возвращает документ через контракт контейнера (Spec: PSR-11 Container, §1.1.2PSR-11 Container §1.1.2). Этот контракт здесь — тихий герой: он позволяет двум разрешениям одного и того же идентификатора вернуть разные экземпляры, и именно так мост даёт вам свежий, одноразовый документ на каждый запрос, сохраняя при этом разобранный реестр шрифтов и кэш изображений как синглтоны на уровне процесса. Долгоживущие воркеры — Octane, RoadRunner, Swoole, Messenger — получают амортизированный разбор шрифтов без утечки состояния между запросами, по построению.
Четыре идиомы различаются только на поверхности:
- 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.
Прочтите диаграмму слева направо, и урок — в симметрии. Каждая поверхность
разрешается в один и тот же Document. Фасад Laravel, фабрика Symfony, сервис
CodeIgniter и самостоятельный конструктор — четыре двери в одну комнату.
Практический пример
Заголовок раздела «Практический пример»Те же три строки намерения, выраженные в каждой идиоме. Тело, которое строит документ — страницы, шрифты, ячейки, подписание, соответствие — идентично во всех четырёх, потому что это один и тот же движок.
<?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();Первые строки — единственное различие. Всё, что после, переносимо: переместите сервис, строящий документ, из Symfony в самостоятельный воркер — и код отрисовки не изменится, потому что контракт, от которого он зависит, не изменился.
Распространённое заблуждение
Заголовок раздела «Распространённое заблуждение»Частое допущение — что мост фреймворка открывает возможности: что долгосрочная
проверка подписи или структурированные электронные счета появляются оттого, что
вы установили nextpdf/laravel, а не вызвали движок напрямую. Это не так. Мост
меняет место вызова, никогда — охват движка. Возможности ядра, такие как вывод
PDF/A и базовое подписание PAdES, открыты и достигают каждой поверхности;
расширенные возможности открываются изданием и затем доступны через любой мост
или самостоятельный путь одинаково. Выбор интеграции с фреймворком — это не выбор
набора функций.
Зеркальное заблуждение — что “один движок” обязательно означает один путь отрисовки для каждого документа. Это не так. Внутрипроцессный движок отрисовывает PDF напрямую; когда документу действительно нужен движок раскладки уровня браузера, этим занимается пакет-отрисовщик. Отрисовка и вызов — отдельные оси; руководство по выбору интеграции — то место, которое их сопоставляет.
Пределы и границы
Заголовок раздела «Пределы и границы»Мост не расширяет то, что движок может отрисовать. Это честный предел, и в нём весь смысл: возможность живёт в ядре и в уровне, а не в адаптере, через который вы до неё дотягиваетесь.
| Edition | Availability |
|---|---|
| Core | Каждый мост (Laravel, Symfony, CodeIgniter) и самостоятельный путь — под Apache-2.0 и работают с ядром. Они адаптируют или раскрывают движок; они не ограничивают функции и не меняют того, что он может создать. |
| Pro | Расширенные возможности, такие как долгосрочная проверка подписи (PAdES B-LT и B-LTA), открываются изданием и затем достигаются одинаково через любой мост или самостоятельный путь — никогда не сменой фреймворка. Архивный вывод PDF/A и базовое подписание PAdES (B-B и B-T) уже в ядре, доступны тем же образом через каждую поверхность. |
| Enterprise | Структурированные электронные счета (EN 16931) и более глубокий инструментарий соответствия — тоже возможности издания, точно так же одинаковые независимо от того, какая поверхность вызывает движок, при том что сама проверка соответствия поставляется в ядре. |
Стоит прямо назвать ещё две границы. Во-первых, каждый мост отслеживает текущую мажорную версию своего фреймворка — Laravel, Symfony и CodeIgniter закрепляют поддерживаемый диапазон, поэтому “любой фреймворк” означает поддерживаемую версию каждого, а не каждый исторический выпуск; считайте собственную документацию каждого пакета авторитетной для его API. Во-вторых, мосты — это адаптеры фреймворков, а не бэкенды отрисовки. Если документу нужен полный браузерный движок раскладки, это выбор отрисовщика, независимый от того, какой фреймворк вызвал движок.
Связанные документы
Заголовок раздела «Связанные документы»- Руководство по выбору интеграции — карта “сценарий — пакет”, включая отрисовщики и поверхность сервиса Connect, когда вам нужно выбирать, а не стандартизировать.
- Открытое ядро, без привязки — почему движок — это актив, а мосты тонкие, поэтому стандартизация вас не запирает.
- Конвейер HTML — что покрывает внутрипроцессный движок, чтобы вы знали, когда браузерный отрисовщик — это отдельный вопрос.
- Основы PHP 8.4 — нижний порог среды выполнения, общий для каждого моста и самостоятельного пути.
Глоссарий
Заголовок раздела «Глоссарий»- Движок ядра —
nextpdf/core, независимый от фреймворка движок PDF 2.0, на котором строятся каждый мост и самостоятельный путь. - Мост фреймворка — интеграционный пакет (Laravel, Symfony, CodeIgniter), который адаптирует движок к идиомам фреймворка — фасад, фабрика, ответ, задание в очереди — не меняя его возможностей.
- Самостоятельный путь — использование движка ядра напрямую, без фреймворка,
путём самостоятельного конструирования
Document; маршрут для инструментов CLI, демонов и библиотек. - Одноразовый документ — контракт
Documentдля однократного использования: построить, выдать, отбросить. Каждое разрешение контейнера возвращает свежий, поэтому состояние не утекает между запросами в долгоживущем воркере. - PAdES — PDF Advanced Electronic Signatures, семейство профилей ETSI для подписания PDF. Базовое подписание (B-B и B-T) в ядре; долгосрочная проверка (B-LT и B-LTA) — возможность расширенного издания. Любое из них достигается через любую поверхность, подробно рассмотрено на страницах о подписании.