跳转到内容

排查 NextPDF Symfony bundle 问题

多数问题集中在四个方面:发现、配置验证、容器接线或 Messenger 路由。以下各节都会把一个症状对应到 bundle 源码中负责验证的行为,并提供一条控制台命令,用来确认修复是否生效。

症状PdfFactory 无法自动注入,或者 debug:container nextpdf 找不到任何条目。

原因:bundle 未加入 config/bundles.php。可能是 Flex 没有执行,也可能是该应用根本没有使用 Flex。

解法

Terminal window
php bin/console debug:container nextpdf

如果结果为空,请手动加入这个 bundle:

return [
NextPDF\Symfony\NextPdfBundle::class => ['all' => true],
];

自动注册提示写在 bundle 的 composer.json 中,位于 extra.symfony.bundles 下。它只会在启用 Flex 的应用中生效。

症状:核心在启动期间抛出 RuntimeException,消息中提到 ext-mbstringext-zlib

原因:这是 bundle 有意设计的快速失败(fail-fast)防护,位于 NextPdfExtension::guardRequiredExtensions()。这不是缺陷。

解法:在 php.ini 中启用消息中指明的扩展,然后重启执行环境。使用以下命令确认:

Terminal window
php -m | grep -E 'mbstring|zlib'

症状:出现 Symfony\Component\Config\Definition\Exception\InvalidConfigurationException,发生于 cache:clearcache:warmup 期间。

原因:某个值超出了 schema 允许的范围。这些限制定义在 Configuration.php 中:

  • page_format 必须是 A4A3A5LetterLegalTabloid 之一。
  • orientation 必须是 PL
  • unit 必须是 ptmmcmin 之一。
  • pdfa 必须是 null44e4f
  • image_cache_mb 必须满足 >= 0

解法:打印合并后的配置,并修正出问题的键:

Terminal window
php bin/console debug:config nextpdf

症状pdfasignature 区段已设置,但输出仍是普通 PDF。

原因:这些功能需要 nextpdf/premiumPdfFactory 只有在编译期检测到 Pro 扩展时,才会应用 PDF/A。编译器流程(compiler pass)只有signature.enabled 为 true signature.certificate 已设置时,才会注册签章器。

解法:确认 Premium 已安装,并且签章器服务确实存在:

Terminal window
composer show nextpdf/premium
php bin/console debug:container --show-private | grep -i signer

如果没有安装 Premium,bundle 会保存该配置,但按设计不会让它生效。bundle 文档中记载的、与 Pro 搭配使用的签章能力,是基准的 B-B 配置文件。NextPDF Premium 文档涵盖 B-B 以外的其他配置文件。

症状artisan 配置被忽略。

原因:Chrome CDP 渲染需要 nextpdf/artisan。编译器流程会在编译期通过 class_exists 探测它。如果缺少这个扩展,renderer(渲染器)就不会接入容器。

解法

Terminal window
composer show nextpdf/artisan
php bin/console cache:clear # re-run the compile-time probe

这项探测会在容器编译期间执行。因此安装完扩展后,需要重新执行一次 cache:clear

症状GeneratePdfMessage 已派送,但没有写出任何 PDF。

原因与解法

  • 消息未路由 — 添加一条路由设置,把 NextPDF\Symfony\Message\GeneratePdfMessage 对应到 config/packages/messenger.yaml 中的某个传输(transport),再启动一个 worker(php bin/console messenger:consume <transport>)。
  • 构建器不在定位器中 — 处理器会使用类字符串 ID 从 PSR-11 定位器(locator)取得构建器。容器标识符是一个字符串,用来唯一标识某个项目(PSR-11 §1.1.2)。如果定位器没有注册该构建器类,处理器就会抛出 RuntimeException,说明所设置的构建器必须实现 PdfBuilderInterface。请先注册该构建器,再从定位器引用它。

查看路由与定位器:

Terminal window
php bin/console debug:messenger
php bin/console debug:container --tag=container.service_locator

消息在派送时被 InvalidArgumentException 拒绝

标题为“消息在派送时被 InvalidArgumentException 拒绝”的章节

症状:构建 GeneratePdfMessage 时抛出 InvalidArgumentException

原因:消息的数据传输对象(DTO)会校验输入。当前会拒绝的规则如下:

  • 输出路径为空,或路径中含有 null 字节;
  • 使用了 stream-wrapper 协议(例如 php://...);
  • 含有 .. 的路径穿越(path-traversal)片段(POSIX 或 Windows 分隔符均适用);
  • 输出路径未以 .pdf 结尾(不区分大小写);
  • 它的 builderClass 不是语法上有效的类名称。

解法:传入一个以 .pdf 结尾的绝对文件系统路径,以及一个真实、完全限定的构建器类名称。

症状:生成的 PDF 含有上一次请求的内容。

原因:某个 Document 实例在长时间运行的 worker 中跨请求被保留下来。文件服务被刻意设置为非共享,正是为了防止这种情况。

解法:在请求作用域内的方法中调用 PdfFactory::create()。切勿把返回的文件存储在共享服务上。

Terminal window
php bin/console debug:container nextpdf # bundle services
php bin/console debug:config nextpdf # merged configuration
php bin/console debug:container --show-private # internal definitions
php bin/console debug:messenger # message routing
php bin/console messenger:consume <t> -vv # verbose consume

每一行都是本页提出的一项规范性主张,并固定关联到一个来自受管 SDO 语料库的完整 64 位十六进制 reference_id。provenance(来源信息)涵盖语料库信息清单与检索传输,记录在 _sidecars/rag-citations.yaml 文件中。

规范条款参考 ID主张
PSR-11psr_11_container#1.1.2.p4容器 has()/get() 标识符合约
  • /integrations/symfony/install/ — 安装与注册。
  • /integrations/symfony/configuration/ — 完整 schema 与限制。
  • /integrations/symfony/boot-and-discovery/ — 发现与启动顺序。
  • /integrations/symfony/security-and-operations/ — 安全标头与路径验证。