从 TCPDF 6.x 迁移到 NextPDF
快速概览
标题为“快速概览”的章节这次迁移遵循一个明确顺序。先以最小幅度的变更切换到 NextPDF 引擎。验证已经可运行的部分。审计尚未正常工作的部分。逐个修正调用点。然后移除适配层。兼容性层支持第二到第四步;它并不是最终目的地。
本页说明迁移策略。若要了解某个具体方法的确切行为,请结合 /integrations/tcpdf-compat/method-coverage/ 与仓库中的权威对照表 docs/TCPDF_COVERAGE.md 一起阅读。
迁移模型
标题为“迁移模型”的章节每个阶段都能让应用程序保持可交付状态。你永远不需要一次性完成整体切换。
阶段 1 — 替换依赖包
标题为“阶段 1 — 替换依赖包”的章节安装 nextpdf/compat-legacy(请参阅 /integrations/tcpdf-compat/install/)。请勿立即移除 tecnickcom/tcpdf——同时保留两者可以方便你进行对比。
选择旧版调用点解析该类的方式:
- **建议做法:**逐文件将
use/require改为use NextPDF\Compat\Tcpdf\TCPDF;。明确,而且可以用 grep 搜索。 - **当你还无法变更调用点时:**在启动时通过
LegacyBootstrap::enableAliases()一次性启用可选的全局别名(请参阅 /integrations/tcpdf-compat/boot-and-discovery/)。这会将\TCPDF以及四个辅助类解析到适配层。
这两种策略在实践中是互斥的。如果真正的 TCPDF 库仍可被自动加载,而你又启用了全局别名, 那么当
\TCPDF类已存在时,别名会被跳过。你可能因此在不知情的情况下继续使用旧版 TCPDF。在阶段 1 期间,建议采用逐文件的导入方式,这样你才能明确知道每个调用点使用的是哪个类。请参阅 /integrations/tcpdf-compat/troubleshooting/.
阶段 2 — 不做变更地执行现有测试套件
标题为“阶段 2 — 不做变更地执行现有测试套件”的章节在不做其他代码变更的情况下,针对适配层执行完整测试套件。大多数委托方法(受测的约 120 个中有 94 个)行为都兼容。你应预期会出现两类可预测的失败:
- **字节级断言。**比对精确 PDF 字节的测试会失败,因为这个引擎是独立实现。这符合预期,并不是缺陷。请将这些延后到阶段 4 处理。
- **返回值分支。**少数方法返回的是兼容性占位值,而不是计算后的数值——最值得注意的是
MultiCell()返回1,而Write()返回0。依赖这些返回值进行分支判断的代码需要调整。
为每一项失败建立清单。将每一项归类为 字节基准、返回值 或 真正的行为差异。
阶段 3 — 严格模式审计
标题为“阶段 3 — 严格模式审计”的章节这是确保迁移安全的阶段。启用严格模式后执行测试套件(或具有代表性的生产环境路径):
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\Exception\TcpdfNotImplementedException;use NextPDF\Compat\Tcpdf\TCPDF;
function renderInvoice(TCPDF $pdf): void{ // ... your existing rendering code, unchanged ...}
$pdf = new TCPDF('P', 'mm', 'A4');$pdf->setStrictMode(true);
try { renderInvoice($pdf); $pdf->Output(__DIR__ . '/audit.pdf', 'F');} catch (TcpdfNotImplementedException $e) { // Each message names the method, the ignored parameters, and a hint. fwrite(STDERR, 'MIGRATION GAP: ' . $e->getMessage() . "\n");}每一个 TcpdfNotImplementedException 都是一项工作项。该消息包含方法名称、被忽略参数的精确清单,以及一条迁移提示。会抛出异常的方法集合,已在 tests/Unit/Compat/Tcpdf/TcpdfStrictModeTest.php 中列出并通过测试断言。每一项背后的原理说明都记录在 docs/TCPDF_COVERAGE.md。
请将严格模式作为专用的 CI 作业执行,而不是在生产环境中执行。它的目的在于暴露差异,而不是让生产环境抛出异常。
阶段 4 — 修正调用点
标题为“阶段 4 — 修正调用点”的章节针对每项差异,选择成本最低且正确的修复方式:
| 差异类型 | 修复方式 |
|---|---|
被忽略的参数无关紧要(e.g. 你从未依赖的 TCPDF $align) | 移除该参数。该调用就会完全兼容。 |
被忽略的参数确实会产生影响(e.g. 可点击的 Image() 链接) | 通过现代化 API 重新表达。先绘制图像,再在该矩形范围上加入 Document::link()。 |
方法尚未实现(setSignature()、endPage()) | endPage() / Open():移除该调用。签名:请参阅 /integrations/tcpdf-compat/security-and-operations/——需要商用版本。 |
不适用的方法(setPDFVersion()、setUserRights()) | 移除。 输出一律为 PDF 2.0;user-rights 在 PDF 2.0 中已弃用。 |
| 返回值分支 | 自行计算该数值,或将该逻辑迁移到现代化 API。 |
对于 TCPDF 接口无法表达的任何内容,请使用以下逃生出口:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();$pdf->AddPage();
// Legacy path stays as-is for the parts that work:$pdf->SetFont('helvetica', '', 12);$pdf->Cell(0, 10, 'Header line', 0, 1);
// Modern path for what the TCPDF surface cannot express here:$document = $pdf->getDocument();$document->image('logo.png', 10, 30, 40, 0);$document->link(10, 30, 40, 20, 'https://example.com');重新建立字节级测试基准
标题为“重新建立字节级测试基准”的章节用针对真正重要事项的断言,取代精确字节断言:
- 输出以
%PDF开头且可以被解析(冒烟测试级别)。 - 已渲染的文本内容存在(提取文本并对其进行断言)。
- 结构属性(页数、页面大小、是否存在大纲)相符。
这是一项一次性成本,并能得到在未来引擎升级后仍然有效的测试。
阶段 5 — 移除 TCPDF 依赖包
标题为“阶段 5 — 移除 TCPDF 依赖包”的章节当严格模式审计通过,生产环境的严格模式保持关闭,并且测试套件在重新建立基准后的断言下全部通过时,即可移除 tecnickcom/tcpdf:
composer remove tecnickcom/tcpdf重新执行测试套件。如果仍有任何内容解析到真正的 TCPDF 类,说明阶段 1 的别名注意事项已经触发——请修正其余调用点,明确导入适配层。
阶段 6 — 淘汰适配层
标题为“阶段 6 — 淘汰适配层”的章节适配层是迁移辅助工具,并不是永久保留的层。在 TCPDF 已移除且引擎已验证后,请逐步淘汰适配层:
- 在每个模块中,将
new TCPDF(...)替换为现代化的NextPDF\Core\Document构建方式。 - 将 TCPDF 方法调用替换为对应的现代化调用(你在阶段 4 已加入的
getDocument()调用就是范本)。 - 当某个模块不再引用适配层时,删除其兼容性导入。
- 当没有任何模块再引用适配层时,将
nextpdf/compat-legacy从composer.json中移除。
此时,你已经运行在现代化的 PDF 2.0 API 之上,不再依赖兼容性层。
迁移检查清单
标题为“迁移检查清单”的章节- 已安装
nextpdf/compat-legacy;引擎连接已验证。 - 调用点已明确导入适配层(或已启用别名,并已将真正的 TCPDF 从自动加载路径中移除)。
- 已针对适配层执行完整测试套件;失败已分类。
- 已加入严格模式 CI 作业;每项差异都已编目记录。
- 每项差异都已修正(移除参数/改用现代化 API/移除调用)。
- 字节级断言已按 content/structure 重新建立基准。
- 已移除
tecnickcom/tcpdf;测试套件全部通过。 - 已逐模块淘汰适配层;依赖包已移除。
另请参阅
标题为“另请参阅”的章节- /integrations/tcpdf-compat/method-coverage/ — 各方法的行为与替换指引
docs/TCPDF_COVERAGE.md— 权威且经测试验证的对照表- /integrations/tcpdf-compat/configuration/ — 将设置从全局常量迁移出去
- /integrations/tcpdf-compat/security-and-operations/ — 迁移期间的加密与签名
- /integrations/tcpdf-compat/troubleshooting/ — alias/real-TCPDF 冲突及其他陷阱