Exception: типизированная иерархия исключений
Каждое исключение, выбрасываемое NextPDF, наследуется от единого абстрактного базового класса NextPdfException, поэтому любую ошибку движка можно обработать одним catch. Каждое доменное исключение реализует ContextAwareExceptionInterface и предоставляет структурированные диагностические поля для журналирования и мониторинга производительности приложений (APM) без разбора текста сообщения.
Установка
Заголовок раздела «Установка»composer require nextpdf/core:^3Концептуальный обзор
Заголовок раздела «Концептуальный обзор»Иерархия состоит из трёх уровней:
RuntimeException (PHP SPL) └── NextPdfException (abstract; implements ContextAwareExceptionInterface) ├── InvalidConfigException ├── FontNotFoundException ├── FontParsingException ├── ImageProcessingException ├── SignatureException ├── EncryptionException ├── WriterException ├── PageLayoutException ├── HtmlParsingException ├── CompressionException ├── NotImplementedException ├── … (23 domain exceptions total) └── Strict\StrictModeViolation (abstract) ├── Strict\IncompatibleRenderingModeException ├── Strict\OracleConformanceFailure └── Strict\UnregisteredCssDeviationNextPdfException наследуется от RuntimeException из стандартной библиотеки PHP (SPL). Если перехватывать RuntimeException, будут перехвачены и ошибки NextPDF. Перехват NextPdfException сужает обработчик до ошибок движка. Для точечного восстановления перехватывайте листовой класс. Поддерево Strict\ группирует нарушения режима соответствия под абстрактным классом StrictModeViolation, который наследуется от NextPdfException.
Контекст вместо строковых кодов. NextPDF идентифицирует ошибку по её типу PHP, а не по строковому коду ошибки. Классы исключений не определяют константу кода NPDF-####. Вместо этого ContextAwareExceptionInterface::getContext() возвращает array<string, mixed> примитивных полей в snake_case, которые безопасно сериализовать в журнал или полезную нагрузку APM. NextPdfException::getContext() по умолчанию возвращает []. Каждое доменное исключение переопределяет этот метод, добавляя поля для соответствующего сбоя. Например, FontNotFoundException::getContext() возвращает font_name, search_paths и fallback_attempted. WriterException возвращает output_path и writer_state. InvalidConfigException возвращает config_key, given_value и expected_type. Стабильные строковые идентификаторы NEXTPDF_W_* относятся к нефатальному перечислению WarningCode в модуле Support, а не к исключениям.
Возможность реагирования. Docblock каждого доменного исключения указывает, кто может на него отреагировать: разработчик, инфраструктура или вызывающая библиотека. InvalidConfigException — это ошибка разработчика; исправьте конфигурацию. FontNotFoundException — это ошибка разработчика или инфраструктуры; проверьте путь или права доступа к файлу. WriterException — это ошибка инфраструктуры; проверьте диск, права доступа или выходной поток. NotImplementedException — это ошибка вызывающего кода; удалите вызов или закрепите версию выпуска, в которой появляется указанная доработка. Несколько исключений предоставляют именованные конструкторы для точного указания первопричин: SignatureException::ltvCapabilityMissing(), ::tsaRequired() и аналогичные. Операторы видят фактическую причину вместо обобщённого сообщения.
Поверхность API
Заголовок раздела «Поверхность API»| Символ | Вид | Ключевые члены |
|---|---|---|
NextPDF\Contracts\ContextAwareExceptionInterface | интерфейс | getContext(): array<string, mixed> |
NextPDF\Exception\NextPdfException | абстрактный класс | наследуется от RuntimeException; getContext() (по умолчанию []) |
NextPDF\Exception\InvalidConfigException | final | getConfigKey(), getGivenValue(), getExpectedType(), getContext() |
NextPDF\Exception\FontNotFoundException | final | getFontName(), getSearchPaths(), wasFallbackAttempted(), getContext() |
NextPDF\Exception\SignatureException | final | getCertInfo(), getSignatureLevel(), getDetail(), getContext(); именованные конструкторы ltvCapabilityMissing(), tsaRequired(), httpClientMissing(), … |
NextPDF\Exception\WriterException | final | getOutputPath(), getWriterState(), getContext() |
NextPDF\Exception\PageLayoutException | final | getPageNumber(), getContext() |
NextPDF\Exception\NotImplementedException | final | $feature, $followUp |
NextPDF\Exception\Strict\StrictModeViolation | abstract | наследуется от NextPdfException |
NextPDF\Exception\Strict\IncompatibleRenderingModeException | final | наследуется от StrictModeViolation |
Полный список листовых классов (23): BarcodeEncoderNotFoundException, BarcodeException, CompressionException, ContentStreamBalanceException, CssParserLimitExceededException, CssResolutionBudgetExceededException, EncryptionException, FontNotFoundException, FontParsingException, GraphicsStateBalanceException, HtmlParsingException, ImageProcessingException, InvalidConfigException, LinearizationInvariantException, LinearizationUnimplementedException, MissingShadingResourceException, NotImplementedException, PageLayoutException, PdfRViolationException, SignatureException, TemplateException, UnsupportedAlgorithmException, WriterException.
Пример кода — быстрый старт
Заголовок раздела «Пример кода — быстрый старт»Чтобы перехватить любую ошибку движка, используйте базовый тип.
<?php
declare(strict_types=1);
use NextPDF\Core\Document;use NextPDF\Exception\NextPdfException;
try { $doc = Document::createStandalone(); $doc->addPage(); $doc->setFont('helvetica', '', 12); $doc->cell(0, 10, 'Hello'); $doc->save('out.pdf');} catch (NextPdfException $e) { \error_log($e->getMessage());}Готовый к запуску пример examples/15-exception-handling.php демонстрирует этот шаблон.
Пример кода — продакшен
Заголовок раздела «Пример кода — продакшен»Выполняйте восстановление на уровне листового класса и передавайте структурированный контекст в конвейер журналирования.
<?php
declare(strict_types=1);
use NextPDF\Contracts\ContextAwareExceptionInterface;use NextPDF\Core\Document;use NextPDF\Exception\FontNotFoundException;use NextPDF\Exception\NextPdfException;use Psr\Log\LoggerInterface;
function render(Document $doc, LoggerInterface $logger): void{ try { $doc->setFont('Brand-Sans', '', 12); $doc->cell(0, 10, 'Invoice'); $doc->save('invoice.pdf'); } catch (FontNotFoundException $e) { // Targeted recovery: fall back to a built-in font. $logger->warning($e->getMessage(), $e->getContext()); $doc->setFont('helvetica', '', 12); $doc->save('invoice.pdf'); } catch (NextPdfException $e) { // Any other engine error: structured context, then rethrow. $context = $e instanceof ContextAwareExceptionInterface ? $e->getContext() : []; $logger->error($e->getMessage(), $context); throw $e; }}Граничные случаи и подводные камни
Заголовок раздела «Граничные случаи и подводные камни»- Порядок перехвата имеет значение. Перечисляйте листовые классы перед
NextPdfException; первыйcatch (NextPdfException)поглощает каждый подкласс. getContext()использует ключи в snake_case, а значения являются примитивами или списками примитивов без вложенных объектов. Полезную нагрузку можно безопасно сериализовать в формат JavaScript Object Notation (JSON).- Базовый
NextPdfException::getContext()возвращает[]. Подкласс, который не переопределяет этот метод, не несёт структурированных полей. В этом случае полагайтесь наgetMessage(). NextPdfExceptionявляется абстрактным; его нельзя инстанцировать напрямую. Выбрасывайте конкретный листовой класс.NotImplementedExceptionнамеренно привлекает внимание. Оно сигнализирует о намеренно отсутствующей реализации, а не о временном сбое. Не пытайтесь повторить операцию.- Исключения
Strict\*сигнализируют о нарушении контракта режима соответствия, а не о восстанавливаемой ошибке времени выполнения. Рассматривайте их как дефекты конфигурации или входных данных. - Константы строкового кода ошибки не существует. Сопоставляйте ошибки по типу исключения. Передавайте
getContext()для машинных потребителей.
Производительность
Заголовок раздела «Производительность»При создании исключения происходит одна аллокация объекта и вызов sprintf, который формирует сообщение: O(1). getContext() возвращает небольшой ассоциативный массив, построенный из уже имеющихся полей: O(1) по количеству полей. Исключения возникают на пути сбоя, а не на горячем пути. Эта стоимость пренебрежимо мала по сравнению с работой, которая завершилась сбоем. По умолчанию performance_budget для этой справочной страницы составляет wall_ms: 1500, peak_mb: 64.
Замечания по безопасности
Заголовок раздела «Замечания по безопасности»Поля контекста могут содержать сведения, полученные из документа. FontNotFoundException включает пути поиска в файловой системе, WriterException включает выходной путь, а InvalidConfigException включает переданное значение. Прежде чем передавать контекст в приёмник журналов с низким уровнем доверия, очистите поля или передайте только список разрешённых ключей, поскольку пути и значения могут раскрыть структуру развёртывания или пользовательский ввод. Сообщения исключений удобочитаемы и могут включать те же сведения. Не показывайте необработанные сообщения конечным пользователям в чувствительном с точки зрения безопасности контексте. SignatureException намеренно включает в сообщение конкретную первопричину, например отсутствующий пакет или пустой Uniform Resource Locator (URL) для Time Stamping Authority (TSA), чтобы операторы могли разобраться в причине без поиска по местам вызова. Эти сведения предназначены для операторов, а не для конечных пользователей.
Соответствие
Заголовок раздела «Соответствие»Этот модуль определяет модель ошибок движка и не содержит нормативной ссылки на стандарт. Исключения, выбрасываемые при нарушениях стандартов, например PdfRViolationException или Strict\OracleConformanceFailure, ссылаются на соответствующий нормативный пункт в модуле, который обнаруживает нарушение, а не здесь.
См. также
Заголовок раздела «См. также»/modules/core/contracts/—ContextAwareExceptionInterface: определение/modules/core/observability/— передачаgetContext()в APM/modules/core/config/—InvalidConfigException,NotImplementedException/modules/core/support/—DegradedException;WarningCode(NEXTPDF_W_*)/modules/core/event/—InvalidConfigExceptionизaddListener()
Глоссарий: контекстно-зависимое исключение · политика деградации