compat-legacy 故障排查
大多数迁移问题都归入少数几种模式。以下每一项都会列出症状、原因和修复方法。当你不确定某个特定方法时,请参阅 /integrations/tcpdf-compat/method-coverage/ 以及仓库中的权威对照表 docs/TCPDF_COVERAGE.md。
进程过去会在 PDF 错误时停止;现在会抛出异常
标题为“进程过去会在 PDF 错误时停止;现在会抛出异常”的章节症状。 之前在渲染失败时会停止的代码,现在会抛出未捕获的 RuntimeException,导致该请求或任务暴露错误。
原因。 旧版 TCPDF 的 Error() 会调用 die()。适配器改为抛出 RuntimeException,这是有意设计,目的是让失败可被观察到。
修复。 将渲染入口点包在 try/catch 中,并将异常映射到你的错误契约。请勿恢复 die() 的行为。请参阅 /integrations/tcpdf-compat/production-usage/ § 失败处理。
new \TCPDF() 仍然解析到真正的 TCPDF 库
标题为“new \TCPDF() 仍然解析到真正的 TCPDF 库”的章节症状。 你已经启用 LegacyBootstrap::enableAliases(),但输出看起来仍像旧版 TCPDF,或者行为没有变化。
原因。 只有在尚未存在同名类时,enableAliases() 才会注册别名。如果 tecnickcom/tcpdf 仍可被自动加载,并且它的 \TCPDF 先加载,别名就会被跳过,你的代码也会继续使用旧版 TCPDF。
修复。 在迁移期间,请优先在各文件中使用显式导入(use NextPDF\Compat\Tcpdf\TCPDF;),确保每个调用处都没有歧义。审计通过后,即可移除 tecnickcom/tcpdf(请参阅 /integrations/tcpdf-compat/migration/ 阶段 5)。请勿在同一个进程中同时运行两套库并启用全局别名。
某个方法「能运作」,但我传入的参数被忽略了
标题为“某个方法「能运作」,但我传入的参数被忽略了”的章节症状。 调用成功并生成了 PDF,但你传入的某个选项(图片链接、对齐、DPI、书签颜色……)没有生效。
原因。 该方法属于静默忽略集合。它为了保持源码兼容性而接受该参数,随后将其丢弃。这是已有文档说明的行为,并非缺陷,请参阅 /integrations/tcpdf-compat/method-coverage/ §2。
修复。 运行严格模式审计,找出每一个这类调用:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\Exception\TcpdfNotImplementedException;use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();$pdf->setStrictMode(true);$pdf->AddPage();$pdf->SetFont('helvetica', '', 12);
try { $pdf->Image('logo.png', 10, 10, 50, 0, '', 'https://example.com');} catch (TcpdfNotImplementedException $e) { // Message lists every ignored parameter and a migration hint. echo $e->getMessage(), "\n";}然后删除该参数,或改用现代 API 重新表达($pdf->getDocument()),如 /integrations/tcpdf-compat/migration/ 阶段 4 所示。
MultiCell() 的返回值永远是 1
标题为“MultiCell() 的返回值永远是 1”的章节症状。 依赖 MultiCell() 返回值进行分支判断的代码(例如用来计算已使用的高度或行数),行为不正确。
原因。 适配器的 MultiCell() 返回的是兼容性占位值 1,而不是实际渲染的 cell/line 数量。Write() 同样返回 0。
修复。 请勿依赖这些返回值进行分支判断。如果你需要渲染后的高度,请改用 getStringHeight() / getNumLines() 计算,或将该逻辑迁移到现代 API。
setPDFVersion('1.4') 并未生成 PDF 1.4 文件
标题为“setPDFVersion('1.4') 并未生成 PDF 1.4 文件”的章节症状。 你请求了较旧的 PDF 版本,但输出仍是 PDF 2.0。
原因。 输出永远是 PDF 2.0(ISO 32000-2)。setPDFVersion() 属于不适用集合;适配器会发出通知并继续运行。
修复。 移除该调用。如果某个下游使用方需要较旧的 PDF 版本,请另行解决该使用方的约束;适配器无法降版输出。
setSignature() 没有任何作用——PDF 并未被签名
标题为“setSignature() 没有任何作用——PDF 并未被签名”的章节症状。 你以证书调用了 setSignature();输出的 PDF 却没有签名。
原因。 通过此适配器调用时,setSignature() 在核心引擎上并未实现。在默认模式下它是无操作;在严格模式下则会抛出异常。
修复。 签名需要商业版 NextPDF 以及现代签名 API。请参阅 /integrations/tcpdf-compat/security-and-operations/ § 数字签名。请勿期望旧版的 setSignature() 调用能签名任何内容。
Output() 损坏了我的 HTTP 响应或 worker 输出
标题为“Output() 损坏了我的 HTTP 响应或 worker 输出”的章节症状。 HTTP 响应中出现二进制乱码,或 worker 日志被 PDF 字节污染。
原因。 你在自行控制响应的场景中,使用了会写入输出路径的输出目标(I/D)。适配器并不会像旧版 TCPDF 那样将内容回显到你的缓冲区,但 I/D 仍会驱动引擎输出。
修复。 在你自行控制的 worker 与处理器中,使用 Output($path, 'F') 写入文件,或使用 Output($name, 'S') 获取字节并自行输出。目标映射(不区分大小写、已去除空白)已在 tests/Unit/Compat/Tcpdf/Bridge/OutputBridgeTest.php 中通过断言验证:
| 代码 | 返回 | 副作用 |
|---|---|---|
S | PDF 字节(%PDF…) | 无 |
F | 空字符串 | 写入文件 |
E | base64 MIME 主体 | 无 |
FI / FD | 空字符串 | 写入文件,然后引擎输出 |
I / D / 未知 | 空字符串 | 引擎输出(内联/下载) |
切换后精确字节级 PDF 断言失败
标题为“切换后精确字节级 PDF 断言失败”的章节症状。 比较原始 PDF 字节的快照测试大量失败。
原因。 该引擎是一套独立的 PDF 2.0 实现。对于委托的方法,可见输出是兼容的,但字节会有所不同。这属于预期行为。
修复。 重新建立基线,改为断言渲染后的内容(提取的文本)、结构(页数、页面尺寸),或执行一次冒烟检查(str_starts_with($bytes, '%PDF'))。请参阅 /integrations/tcpdf-compat/migration/ 阶段 4。
某个旧版 K_* / PDF_* 常量的值不正确
标题为“某个旧版 K_* / PDF_* 常量的值不正确”的章节症状。 你通过常量设置的自定义路径或默认值未生效。
原因。 只有在常量尚未定义时,适配器才会自动定义它,而且是在首次构造时进行。如果你的 define() 在首个适配器构造之后才运行,则适配器的默认值已经生效。
修复。 在你的引导程序中、创建任何适配器实例之前,定义所有自定义 K_* / PDF_* 常量。请参阅 /integrations/tcpdf-compat/configuration/ § 配置解析顺序。
构造时引擎版本不匹配
标题为“构造时引擎版本不匹配”的章节症状。 在依赖更新后,构造失败或行为异常。
原因。 适配器需要 nextpdf/core ^3.0。如果解析出的核心版本超出该范围,则不受支持。
修复。 运行 composer show nextpdf/core,并将引擎固定到 ^3.0。请参阅 /integrations/tcpdf-compat/install/ § 验证引擎版本。
诊断快速参考
标题为“诊断快速参考”的章节| 问题 | 在哪里查看 |
|---|---|
| 方法 X 在这里实际做了什么? | /integrations/tcpdf-compat/method-coverage/、docs/TCPDF_COVERAGE.md |
| 我的哪些调用会丢失参数? | 严格模式审计(本页;/integrations/tcpdf-compat/migration/) |
| 为什么进程没有在出错时停止? | /integrations/tcpdf-compat/security-and-operations/ § 强化行为 |
| 为什么输出未被签名 / 不是 PDF/A? | /integrations/tcpdf-compat/security-and-operations/ |
| 别名与显式导入的冲突 | 本页;/integrations/tcpdf-compat/boot-and-discovery/ |
另请参阅
标题为“另请参阅”的章节- /integrations/tcpdf-compat/migration/ —— 分阶段迁移可以避免上述大多数问题
- /integrations/tcpdf-compat/method-coverage/ —— 逐方法行为参考
- /integrations/tcpdf-compat/boot-and-discovery/ —— 别名注册与冲突规避
docs/TCPDF_COVERAGE.md—— 权威覆盖对照表