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

Загрузка и обнаружение NextPDF Artisan

Artisan — обычная библиотека, которая следует рекомендации PHP Standard Recommendation 4 (PSR-4). У неё нет ни сервис-провайдера, ни bundle, ни манифеста автообнаружения фреймворка. Она загружается, как только её классы становятся доступны автозагрузчику. Обнаружение здесь — это карта PSR-4 в Composer, и ничего более.

Файл composer.json пакета объявляет два корня PSR-4: NextPDF\Artisan\src/Artisan/ и NextPDF\Parser\src/Parser/. В нём нет ни extra.laravel, ни класса bundle для Symfony, ни регистратора для CodeIgniter. Во время загрузки ничего не сканируется, не регистрируется и не подключается через хуки.

Точка интеграции находится в nextpdf/core. Document (через трейт HasTextOutput) предоставляет метод writeHtmlChrome(), который во время выполнения проверяет class_exists() для NextPDF\Parser\PdfReader и NextPDF\Artisan\PageImporter. Если автозагрузчик может разрешить оба класса, путь Chrome доступен. Если не может, core выбрасывает исключение макета вместо аварийного завершения с фатальной ошибкой. По сути, обнаружение сводится к одному вопросу: зарегистрированы ли классы Artisan в автозагрузчике? Ответ даёт Composer; механизмы фреймворка здесь не участвуют.

Это сделано намеренно. Мост — это возможность, к которой ядро движка обращается через границу пакета, а не сервис под управлением фреймворка. Artisan одинаково работает в Laravel, Symfony, CodeIgniter, CLI-скрипте или обработчике очереди, потому что ни одна из этих сред ему не требуется.

no

yes

Composer autoload (PSR-4)

Application constructs Document

Document::setChromeRendererConfig(config)

Document::writeHtmlChrome(html)

class_exists PdfReader

and PageImporter?

core raises layout exception

resolve ChromeHtmlRenderer

render → parse → import Form XObject

Diagram

У Artisan нет ни загрузочного ядра, ни регистрации команд, ни фазы отложенных провайдеров. Первый вызов writeHtmlChrome() и есть вся точка входа в жизненный цикл.

У Artisan нет контейнера внедрения зависимостей (DI), и он не регистрирует никаких привязок. Его компоненты — обычные объекты, внедряемые через конструктор: создайте ChromeRendererConfig, передайте его в ChromeHtmlRenderer и при необходимости внедрите логгер PSR-3 и собственный HtmlSecurityPolicyInterface. В контейнере хостовой среды зарегистрируйте ChromeHtmlRenderer как singleton самостоятельно; см. пример на /integrations/artisan/production-usage/.

Некоторые возможности NextPDF, включая контракты e-invoice уровня Premium, обычно разрешаются через контейнер фреймворка. Artisan также работает в средах без контейнера: инструментах CLI, автономных скриптах и пользовательских исполнителях. Поэтому он поставляется с EInvoiceServiceFactory:

МетодВозвращаетКогда null
makeEmbedder()EmbedderInterface (уровень Pro)Уровень Pro не установлен
makeValidator()ValidatorInterface (уровень Enterprise)Уровень Enterprise не установлен
makeDefaultProfile()ProfileInterface (EN16931, уровень Pro)Уровень Pro не установлен
makeSchematronRunner()SchematronRunnerInterface (уровень Enterprise)Уровень Enterprise не установлен

Каждый вызов возвращает новый экземпляр. Такая одноразовая выдача важна, поскольку вызовы embed и validate владеют изменяемым контекстом разбора Extensible Markup Language (XML) и не должны разделять состояние. Фабрика — удобство для редкого сценария без контейнера, а не локатор сервисов. Предпочтительный шаблон по-прежнему — собирать объекты при создании и передавать их как аргументы конструктора. Возврат null при отсутствии уровня повторяет поведение пакетов-обёрток для фреймворков, поэтому один и тот же вызывающий код работает и с Premium, и без него. Источник: src/Artisan/EInvoiceServiceFactory.php; интеграционно протестировано в tests/Integration/Artisan/EInvoiceServiceFactoryIntegrationTest.php.

Каскада конфигурационных файлов нет. Конфигурация — это ровно то, что вы передаёте в ChromeRendererConfig:

  1. Аргументы конструктора, которые вы передаёте явно, либо
  2. ChromeRendererConfig::fromArray() из массива, предоставленного хостовой средой (ключи в snake-case; неустановленные ключи возвращаются к значениям конструктора по умолчанию; chrome_binary применяется только тогда, когда это непустая строка).

Разрешённая конфигурация неизменна в течение всего времени жизни рендерера. Все ключи см. на /integrations/artisan/configuration/.

  • “Обнаруживается ли мост?” — если class_exists(\NextPDF\Artisan\PageImporter::class) возвращает true, автозагрузчик Composer может найти мост, и core будет использовать путь Chrome.
  • “Загрузился ли он?” — фазы загрузки, которая могла бы завершиться ошибкой, нет; отсутствующая зависимость проявляется при первом вызове writeHtmlChrome() как типизированное исключение, сопоставленное на /integrations/artisan/troubleshooting/.
  • Проверка Premium без контейнераEInvoiceServiceFactory::makeEmbedder() === null означает, что уровень Pro не установлен; путь отрисовки с открытым исходным кодом при этом не затрагивается.
  • /integrations/artisan/integration/ — интеграция
  • /integrations/artisan/overview/ — обзор
  • /integrations/artisan/configuration/ — настройка
  • /integrations/artisan/production-usage/ — использование в продакшене
  • /integrations/artisan/troubleshooting/ — устранение неполадок