NextPDF: обзор интеграции с Laravel
Краткий обзор
Заголовок раздела «Краткий обзор»Пакет nextpdf/laravel подключает PDF-движок NextPDF к вашему приложению Laravel 12 и сам регистрирует привязки контейнера. Он включает фасад Pdf, HTTP-помощник PdfResponse и задачу GeneratePdfJob, которую можно ставить в очередь. Laravel автоматически обнаруживает пакет, поэтому регистрировать его вручную не нужно.
Установка
Заголовок раздела «Установка»composer require nextpdf/laravelОграничение Composer задано как nextpdf/core: ^3.0 || ^5.2. Пакет также
требует laravel/framework: ^12.0 и php: >=8.4 <9.0. Полную процедуру, включая публикацию конфигурации и дополнительные расширения, см. на странице /integrations/laravel/install/.
Концептуальный обзор
Заголовок раздела «Концептуальный обзор»Пакет находится между сервис-контейнером Laravel и независимым от фреймворка ядром NextPDF. Он не реализует генерацию PDF с нуля. Вместо этого он адаптирует модель ядра NextPDF\Core\Document к жизненному циклу, конфигурации, очередям и HTTP-слою Laravel.
Схема ниже показывает путь запроса от кода вашего приложения через пакет к общим реестрам ядра.
В карте автозагрузки есть одна запись PSR-4. PSR-4 — это стандартная рекомендация PHP по автозагрузке, и её префикс NextPDF\Laravel\ сопоставлен с src/Laravel/. Согласно PSR-4 префикс пространства имён соответствует базовому каталогу, а оставшаяся часть имени класса — пути к файлу в этом каталоге (PSR-4 §3). Под этим префиксом находятся четыре основных класса:
NextPDF\Laravel\NextPdfServiceProvider— регистрирует привязки и публикует конфигурацию.NextPDF\Laravel\Facades\Pdf— статический прокси, который разрешает новый документ из контейнера.NextPDF\Laravel\Http\PdfResponse— создаёт inline, download и потоковые PDF-ответы с фиксированным набором заголовков безопасности.NextPDF\Laravel\Jobs\GeneratePdfJob— задача для очереди, которая собирает и сохраняет PDF на воркере.
Поставщик служб реализует DeferrableProvider, поэтому регистрирует свои привязки только тогда, когда вы разрешаете одну из объявленных записей. Такая отложенная регистрация не утяжеляет путь загрузки фреймворка. Метод provides() провайдера перечисляет отложенные записи, а контейнер читает этот список, чтобы сопоставить каждый ключ с провайдером.
Разрешение следует контракту контейнера: когда привязка существует, разрешение идентификатора возвращает зарегистрированную запись. PSR-11 — это стандартная рекомендация PHP по совместимости контейнеров, и в ней указано, что два последовательных вызова get() с одним и тем же идентификатором могут возвращать разные значения в зависимости от стратегии привязки (PSR-11 §1.1.2). NextPDF намеренно опирается на это поведение. Реестры являются синглтонами, поэтому каждое разрешение возвращает один и тот же экземпляр. Документы привязаны через фабрику, поэтому каждое разрешение возвращает новый экземпляр. Полную таблицу времени жизни привязок см. на странице /integrations/laravel/boot-and-discovery/.
Архитектура рассчитана на долгоживущие воркеры, такие как Octane, RoadRunner и Swoole. Реестр шрифтов — это синглтон на время жизни процесса: пакет один раз прогревает его, а затем блокирует, поэтому ни один запрос не может изменить общее состояние шрифтов. Реестр изображений — это синглтон на время жизни процесса с ограниченным кэшем, который вытесняет наименее недавно использованные элементы (LRU). Поскольку пакет всегда создаёт каждый документ через DocumentFactory, изменяемое состояние одного запроса никогда не утекает в другой запрос.
Поверхность API
Заголовок раздела «Поверхность API»| Класс | Публичная точка входа | Возвращает | Назначение |
|---|---|---|---|
NextPdfServiceProvider | register(), boot(), provides() | void / array | Привязки контейнера, публикация конфигурации, список отложенных записей |
Facades\Pdf | статический прокси (addPage(), cell(), save(), …) | static / mixed | Разрешает PdfDocumentInterface при каждом вызове |
Http\PdfResponse | inline(), download(), streamInline(), streamDownload() | Response / StreamedResponse | HTTP-ответы с заголовками Open Worldwide Application Security Project (OWASP) |
Jobs\GeneratePdfJob | dispatch(), handle(), then(), catch(), failed() | PendingDispatch / void / self | Генерация PDF в очереди |
Ключи контейнера, привязываемые провайдером:
| Ключ | Время жизни | Разрешается в |
|---|---|---|
NextPDF\Contracts\FontRegistryInterface (псевдоним FontRegistry) | синглтон, заблокирован | NextPDF\Typography\FontRegistry |
NextPDF\Graphics\ImageRegistry | синглтон, ограничен LRU-кэшем | ImageRegistry |
NextPDF\Contracts\DocumentFactoryInterface (псевдоним DocumentFactory) | синглтон | NextPDF\Core\DocumentFactory |
Psr\Http\Client\ClientInterface | синглтон | SecurityAwareHttpClient, оборачивающий CurlHttpClient |
NextPDF\Security\Timestamp\TsaClient | ограниченная областью | TsaClient или null, если нет URL службы меток времени (TSA) |
NextPDF\Contracts\SignerInterface | фабрика | DigitalSigner или null, если подписание отключено |
NextPDF\Contracts\PdfDocumentInterface (псевдоним nextpdf) | фабрика | NextPDF\Core\Document |
NextPDF\Contracts\EInvoice\{Embedder,Validator,Profile,SchematronRunner}Interface | фабрика | разрешается только, когда nextpdf/premium установлен |
Пример кода — быстрый старт
Заголовок раздела «Пример кода — быстрый старт»<?php
declare(strict_types=1);
use NextPDF\Laravel\Facades\Pdf;
Pdf::addPage();Pdf::cell(0, 10, 'Hello from Laravel', newLine: true);Pdf::save(storage_path('app/hello.pdf'));Готовый к запуску пример контроллера см. на странице /integrations/laravel/quickstart/.
Пример кода — продакшен
Заголовок раздела «Пример кода — продакшен»В продакшен-паттерне контракт документа разрешается из контейнера, а не из фасада: так место вызова остаётся явным и пригодным для тестирования. Полный контроллер, включая внедрение зависимостей (DI) и обработку ошибок, см. на странице /integrations/laravel/production-usage/.
<?php
declare(strict_types=1);
use NextPDF\Contracts\PdfDocumentInterface;use NextPDF\Laravel\Http\PdfResponse;
$document = app(PdfDocumentInterface::class);$document->addPage();$document->cell(0, 10, 'Invoice', newLine: true);
return PdfResponse::download($document, 'invoice.pdf');Граничные случаи и подводные камни
Заголовок раздела «Граничные случаи и подводные камни»- Провайдер отложенный, поэтому разрешение несвязанного ключа контейнера не запускает NextPDF. Привязки появляются только тогда, когда вы запрашиваете одну из записей
provides(). SignerInterfaceиTsaClientпо замыслу разрешаются вnull, когда вы не настроили подписание или службу меток времени. Ваш код должен проверять результат на null; не предполагайте, что экземпляр существует.- Привязки контрактов электронных счетов регистрируются всегда, но разрешаются в конкретные реализации Premium, которые существуют только тогда, когда установлен
nextpdf/premium. Их разрешение без Premium вызывает ошибку “класс не найден”, и эта ошибка появляется при первом разрешении, а не при загрузке. - Фасад возвращает новый документ при каждом разрешении. Рассмотрим два статических вызова
Pdf::в одном запросе, разделённыеPdf::clearResolvedInstances(): эти вызовы работают с разными документами.
Производительность
Заголовок раздела «Производительность»Регистрация провайдера выполняется за время O(1). Провайдер привязывает замыкания и не конструирует тяжёлые объекты, поэтому стоимость конструирования откладывается до первого разрешения. Прогрев реестра шрифтов выполняется за время O(f), где f — количество предзагруженных файлов шрифтов, и запускается один раз на процесс-воркер. Это распределяет задержку первого запроса в долгоживущих воркерах. Бюджет памяти на страницу для этого обзора зафиксирован в поле фронтматтера performance_budget.
Замечания по безопасности
Заголовок раздела «Замечания по безопасности»PdfResponse применяет фиксированный набор заголовков Open Worldwide Application Security Project (OWASP). В него входят X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Content-Security-Policy: default-src 'none', X-Robots-Tag и Referrer-Policy: no-referrer. GeneratePdfJob проверяет путь вывода на стороне воркера, что снижает риск от подделанных сериализованных данных. Полную модель угроз и конфигурацию развёртывания см. на странице /integrations/laravel/security-and-operations/.
Соответствие стандартам
Заголовок раздела «Соответствие стандартам»| Утверждение | Источник | Пункт | reference_id (идентификатор) |
|---|---|---|---|
| Семантика разрешения и времени жизни в контейнере | PSR-11 Container (контейнер) | §1.1.2 | |
| Сопоставление префикса автозагрузки PSR-4 | PSR-4 Autoloader (автозагрузчик) | §3 |
Коммерческий контекст
Заголовок раздела «Коммерческий контекст»Когда установлен nextpdf/premium, тот же провайдер предоставляет дополнительные возможности: цифровое подписание (PAdES B-B), архивирование PDF/A и привязки контрактов электронных счетов. Он предоставляет их через те же ключи контейнера, поэтому описанному здесь пакету Core не требуются изменения в коде, чтобы воспользоваться этими возможностями. Подробнее см.
https://nextpdf.dev/get-license/?intent=laravel-signing.
См. также
Заголовок раздела «См. также»- /integrations/laravel/install/ — процедура установки и дополнительные расширения
- /integrations/laravel/quickstart/ — готовый к запуску пример контроллера
- /integrations/laravel/configuration/ — каждый ключ конфигурации, сверенный с
config/nextpdf.php - /integrations/laravel/production-usage/ — контроллер с внедрением зависимостей (DI), обработка ошибок, постановка в очередь
- /integrations/laravel/boot-and-discovery/ — автообнаружение и время жизни привязок
- /integrations/laravel/security-and-operations/ — модель угроз и конфигурация развёртывания