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

NextPDF для CodeIgniter 4

nextpdf/codeigniter подключает движок NextPDF для Portable Document Format (PDF) к приложению CodeIgniter 4 через слой Services фреймворка. PDF-документы можно создавать в контроллерах, задачах или командах, а затем возвращать как нативные ответы CodeIgniter по протоколу Hypertext Transfer Protocol (HTTP).

Окно терминала
composer require nextpdf/codeigniter

В файле composer.json пакета указаны требования: php >=8.4 <9.0, nextpdf/core ^3.0 || ^5.2 и codeigniter4/framework ^4.6. Также пакет рекомендует nextpdf/artisan, nextpdf/premium и codeigniter4/queue. Полную таблицу требований, необязательные пакеты и шаги проверки см. в /integrations/codeigniter/install/.

NextPDF — это движок PDF 2.0 на PHP 8.4. Базовый движок (nextpdf/core) не зависит от фреймворка: он ничего не знает о HTTP, маршрутизации и связывании зависимостей. nextpdf/codeigniter — адаптер, который подключает движок к приложению CodeIgniter 4. После установки адаптера не нужно вручную настраивать реестры, фабрики и обработку ответов.

Пакет добавляет в приложение CodeIgniter 4 четыре вещи:

  • Класс Services (NextPDF\CodeIgniter\Config\Services), который CodeIgniter обнаруживает автоматически. Он предоставляет именованные сервисы: fontRegistry, imageRegistry, documentFactory, pdfDocument, pdf, tsaClient и pdfSigner.
  • Библиотека Pdf (NextPDF\CodeIgniter\Libraries\Pdf) — высокоуровневый интерфейс application programming interface (API) для контроллеров. Она оборачивает один одноразовый документ и за один вызов превращает его в ответ.
  • Помощник PdfResponse (NextPDF\CodeIgniter\Http\PdfResponse), который создаёт DownloadResponse CodeIgniter для встроенного просмотра или загрузки. Он добавляет фиксированный набор заголовков, которые усиливают защиту ответа.
  • Две глобальные вспомогательные функцииpdf() и pdf_document(). Они регистрируются через запись автозагрузки files в Composer и через Registrar пакета.

Пакет также обнаруживает необязательные расширения NextPDF при сборке документа. Если установлен nextpdf/artisan и настроен исполняемый файл Chrome, документ получает отрисовщик Chrome. Если установлен NextPDF Pro, вывод PDF/A и цифровая подпись доступны через тот же набор Services. Обнаружение выполняется условно и без вывода сообщений. Пакет никогда не требует отсутствующее расширение.

Почему класс Services, а не привязка в контейнере

Заголовок раздела «Почему класс Services, а не привязка в контейнере»

CodeIgniter 4 не поставляется с контейнером внедрения зависимостей PSR-11. Вместо этого он использует локатор Services. Локатор Services — это класс со статическими фабричными методами, который фреймворк может обнаружить. Каждый метод возвращает либо общий экземпляр, либо новый. В PSR-11 §1.3 паттерн service locator — передача контейнера в объект, чтобы тот сам извлекал свои зависимости, — помечен модальным глаголом SHOULD NOT. Пакет следует соглашению о локаторах CodeIgniter. При этом поверхность локатора остаётся минимальной и явной: каждый сервис — это именованный фабричный метод с параметром bool $getShared, и вызывающий код получает конкретные объекты, а не дескриптор контейнера.

Благодаря этому интеграция CodeIgniter согласована с интеграциями Laravel и Symfony. Каждая интеграция предоставляет одни и те же логические сервисы через идиому своего фреймворка.

Точка входаТипВозвращаетВремя жизни
Services::fontRegistry()сервисFontRegistryInterfaceобщий (прогрет, затем заблокирован)
Services::imageRegistry()сервисImageRegistryобщий (ограниченный кэш least recently used (LRU))
Services::documentFactory()сервисDocumentFactoryInterfaceобщий (без состояния)
Services::pdfDocument(false)сервисNextPDF\Core\Documentновый при каждом вызове
Services::pdf(false)сервисNextPDF\CodeIgniter\Libraries\Pdfновый при каждом вызове
Services::tsaClient()сервис?TsaClientобщий; null, когда нет URL центра меток времени (TSA)
Services::pdfSigner(false)сервис?SignerInterfaceновый; null, когда подпись отключена
pdf()помощникPdfновый при каждом вызове
pdf_document()помощникDocumentновый при каждом вызове
PdfResponse::inline() / download()статическийDownloadResponseна вызов
GeneratePdfJobзадача очередиодна на отправку

Контроллер возвращает PDF в три строки. Services::pdf() возвращает новый экземпляр библиотеки Pdf, которая оборачивает новый документ. Затем download() создаёт DownloadResponse CodeIgniter.

<?php
declare(strict_types=1);
namespace App\Controllers;
use CodeIgniter\HTTP\DownloadResponse;
use NextPDF\CodeIgniter\Config\Services;
final class InvoiceController extends BaseController
{
public function download(int $id): DownloadResponse
{
$pdf = Services::pdf();
$pdf->document()->addPage();
$pdf->document()->cell(0, 10, "Invoice #{$id}");
return $pdf->download("invoice-{$id}.pdf");
}
}

Полное пошаговое руководство, которое можно запустить, находится в /integrations/codeigniter/quickstart/. В нём разобраны маршрутизация, встроенный просмотр и варианты с помощниками pdf() и pdf_document().

В продакшене запрашивайте отдельный экземпляр через Services::pdf(false). Перехватывайте единое базовое исключение, NextPDF\Exception\NextPdfException; все ошибки ядра и расширений наследуются от него. Логируйте сбой с контекстом, а не подавляйте ошибку.

try {
$pdf = Services::pdf(false);
$pdf->document()->addPage();
$pdf->document()->cell(0, 10, "Invoice #{$id}");
return $pdf->download("invoice-{$id}.pdf");
} catch (NextPdfException $e) {
$logger->error('pdf.invoice.failed', [
'invoice_id' => $id,
'exception' => $e::class,
'message' => $e->getMessage(),
]);
return $this->response
->setStatusCode(ResponseInterface::HTTP_INTERNAL_SERVER_ERROR)
->setJSON(['error' => 'pdf_generation_failed', 'invoice_id' => $id]);
}

Полный продакшен-контроллер находится в /integrations/codeigniter/production-usage/. Он добавляет тайминг для наблюдаемости, безопасное время жизни для воркеров и асинхронную генерацию.

  • Реестры шрифтов и изображений — это синглтоны на время жизни процесса. Документ никогда не разделяется между вызовами. pdfDocument и pdf при каждом вызове возвращают новый экземпляр, поэтому один запрос не может передать содержимое в другой. Services::pdf(false) и pdf() оба возвращают новый экземпляр библиотеки, которая оборачивает новый документ.
  • Пакет требует PHP-расширений mbstring и zlib. Реестр шрифтов проверяет их один раз за процесс. Если какого-либо из расширений нет, реестр шрифтов выбрасывает ошибку времени выполнения с указанием отсутствующего расширения.
  • Поведение необязательных расширений зависит от того, что установлено в том же приложении. Когда присутствует только nextpdf/core, пути подписи и PDF/A возвращают null или пропускаются. Они никогда не завершаются шумной ошибкой.

Интеграция не добавляет измеримых накладных расходов сверх самого движка. Реестр шрифтов разбирается один раз, а затем блокируется. Реестр изображений — это кэш LRU, ограниченный настройкой imageCacheMb (50 MB по умолчанию). Затраты на сборку PDF определяют базовый движок и содержимое документа, а не адаптер. Бюджет на страницу для этого набора документации составляет 1500 ms по времени / 128 MB пиковой памяти. Отдельные рецепты задают собственный бюджет во фронтматтере.

PdfResponse добавляет фиксированный набор заголовков ответа к каждому выдаваемому PDF: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Content-Security-Policy: default-src 'none', X-Robots-Tag: noindex, nofollow и Referrer-Policy: no-referrer. Имена файлов очищаются, а имена вне ASCII передаются с расширенным параметром Request for Comments (RFC) 5987. Задача очереди ограничивает вызываемые билдеры пространством имён App\PdfBuilders и ограничивает пути вывода каталогом WRITEPATH/pdfs/. Полную модель угроз см. в /integrations/codeigniter/security-and-operations/.

  • Обнаружение модулей опирается на автозагрузку PSR-4 в Composer. Префикс пространства имён сопоставляется с базовым каталогом, а полностью квалифицированное имя класса — с путём к файлу (PSR-4 §x1.x3).
  • Дизайн Services следует рекомендациям по локаторам, обсуждаемым в PSR-11 §1.3.

Ядро NextPDF распространяется под лицензией Apache-2.0. Цифровые подписи, архивирование PDF/A и встраивание электронных счетов Factur-X предоставляются NextPDF Pro и NextPDF Enterprise. Пакет CodeIgniter предоставляет соответствующие сервисные методы. Эти методы возвращают null, пока в том же приложении не установлен соответствующий пакет Premium.

  • /integrations/codeigniter/install/ — установка и проверка пакета.
  • /integrations/codeigniter/quickstart/ — первый PDF в контроллере.
  • /integrations/codeigniter/configuration/ — каждый ключ конфигурации.
  • /integrations/codeigniter/boot-and-discovery/ — как CodeIgniter находит класс Services.
  • /integrations/codeigniter/integration/ — справочник по подключению и дымовой тест.