Перейти к содержимому
getnextpdf.com

Один движок, любой фреймворк

Spec: PSR-11 Container, §1.1.2Spec: PSR-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, демона или библиотеки нет фреймворка, от которого можно строить мост; они конструируют документ напрямую.
  • Одна модель документа путешествует по всем четырём. Одни и те же объекты-значения, перечисления и контракт вывода появляются везде, поэтому документ перемещается между местами вызова без изменений.

Архитектура — это намеренное разделение. Движок — это актив; мост — тонкий адаптер, который говорит на идиомах одного фреймворка. Мост регистрирует небольшое пространство имён поверх общего ядра через стандартную автозагрузку (Spec: PSR-4 Autoloader, §3) и возвращает документ через контракт контейнера (Spec: PSR-11 Container, §1.1.2). Этот контракт здесь — тихий герой: он позволяет двум разрешениям одного и того же идентификатора вернуть разные экземпляры, и именно так мост даёт вам свежий, одноразовый документ на каждый запрос, сохраняя при этом разобранный реестр шрифтов и кэш изображений как синглтоны на уровне процесса. Долгоживущие воркеры — Octane, RoadRunner, Swoole, Messenger — получают амортизированный разбор шрифтов без утечки состояния между запросами, по построению.

Четыре идиомы различаются только на поверхности:

  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.
One framework-agnostic core engine reached through four idiomatic surfaces: a Laravel facade, an injected Symfony factory, a CodeIgniter service, or a directly constructed standalone document — each handing back the same disposable Document model.

Прочтите диаграмму слева направо, и урок — в симметрии. Каждая поверхность разрешается в один и тот же 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 напрямую; когда документу действительно нужен движок раскладки уровня браузера, этим занимается пакет-отрисовщик. Отрисовка и вызов — отдельные оси; руководство по выбору интеграции — то место, которое их сопоставляет.

Мост не расширяет то, что движок может отрисовать. Это честный предел, и в нём весь смысл: возможность живёт в ядре и в уровне, а не в адаптере, через который вы до неё дотягиваетесь.

Framework bridges over one engine — edition availability
EditionAvailability
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) — возможность расширенного издания. Любое из них достигается через любую поверхность, подробно рассмотрено на страницах о подписании.