NextPDF compat-legacy 的 TCPDF 方法覆盖范围
nextpdf/compat-legacy 是一个兼容层,并非 TCPDF 的分支,也不是保证行为一致的复制品。它基于 NextPDF 核心引擎,公开 TCPDF 6.x 的公开方法名称、参数顺序和默认值。大多数调用会直接映射到一项 NextPDF Document 操作。少数已界定的方法,要么接受 NextPDF 并不采纳的旧版参数,要么完全没有作用。
本页是逐方法审计的读者版摘要。具权威性、经测试验证的覆盖范围矩阵位于仓库中的 docs/TCPDF_COVERAGE.md。当本页与仓库内矩阵不一致时,以仓库内矩阵为准,因为该矩阵由测试套件断言。
在迁移之前,请用本页回答一个问题:对于我的代码基底所调用的每一个 TCPDF 方法,适配器实际上会做什么?
覆盖范围摘要
标题为“覆盖范围摘要”的章节本次审计审视了约 120 个 TCPDF 6.x 公开方法。每个方法都被归入四个类别之一。
| 类别 | 数量 | 对你的意义 |
|---|---|---|
| 镜像 — 完全委派 | 94 | 此调用直接映射到一项 NextPDF Document 方法。就所记录的参数而言,行为是兼容的。 |
| 静默忽略 — 部分 | 15 | 此方法会执行并产生输出,但有一个或多个 TCPDF 参数不会产生任何作用。这是一项已记录的行为差异。 |
| 未实现 — 空主体 | 4 | 此方法为源代码兼容性而存在,但不做任何事。 |
| 不适用 | 7 | 此 TCPDF 方法对 PDF 输出没有任何作用;刻意排除。 |
| 新增的现代 API 偏移方法 | 17 | NextPDF v5.1+ 在适配器上公开的 Document 方法,使混用 API 的代码得以编译。没有对应的 TCPDF 6.x 方法。 |
这些数字来自 docs/TCPDF_COVERAGE.md §Summary。该矩阵由 tests/Unit/Compat/Tcpdf/TcpdfApiDriftTest.php 和 tests/Unit/Compat/Tcpdf/TcpdfStrictModeTest.php 验证。
用语说明。 本软件包并不宣称自己是「直接替换」 (drop-in replacement)或「100% 与 TCPDF 兼容」。它通过直接委派覆盖了所审视约 120 个 TCPDF 方法中的 94 个;其余方法带有下文所述、已记录的行为差异。更准确的说法是「与 TCPDF 兼容的替代方案」,并具备「已知且经测试的兼容接口」。
关于方法数量的说明
标题为“关于方法数量的说明”的章节适配器由 25 个单一职责的 concern trait(src/Compat/Tcpdf/Concerns/)构成,总共公开 273 个公开方法,另有少数生命周期方法和逃生口(escape-hatch)方法位于 TCPDF 类本身。上述覆盖范围类别统计的是不重复的 TCPDF 6.x API 接口方法(约 120 个),而不是适配器公开方法的总数。这两个数字衡量的是不同对象:API 接口覆盖范围与实现规模。如果你在软件包 README.md 中看到较少的 trait 数量或方法数量,请以 docs/TCPDF_COVERAGE.md 和本页为准 — README 摘要早于 AdaptsDriftV51 trait。
1. 镜像方法 — 兼容委派
标题为“1. 镜像方法 — 兼容委派”的章节有九十四个方法会直接映射到底层的 NextPDF\Core\Document 实例。在引擎使用 camelCase 的位置,PascalCase 的 TCPDF 名称会映射到 camelCase 的 NextPDF 名称;适配器同时接受两种拼写,以兼顾向前和向后兼容性。
具代表性的群组(完整表格:docs/TCPDF_COVERAGE.md §1):
| TCPDF 领域 | 范例方法 | 适配器 trait |
|---|---|---|
| 生命周期 | Output(), Close(), getPDFData() | AdaptsLifecycle |
| 页面 | AddPage(), getNumPages(), deletePage() | AdaptsPageManagement |
| 文字 | Cell(), MultiCell(), Write(), Text(), Ln() | AdaptsTextOutput |
| 字体 | SetFont(), SetFontSize(), AddFont() | AdaptsFonts |
| 色彩 | SetTextColor(), SetDrawColor(), SetFillColor() | AdaptsColors |
| 绘图 | Line(), Rect(), Circle(), Polygon(), Arrow() | AdaptsDrawing |
| 变换 | Rotate(), Scale(), Translate(), Skew(), Mirror*() | AdaptsTransforms |
| 导览 | AddLink(), Annotation(), addTOC() | AdaptsNavigation |
对这些方法而言,就 NextPDF 所记录的参数来看,观察到的行为与 TCPDF 6.x 兼容。适配器并不断言会生成字节完全相同的 PDF 输出。底层引擎是一套独立的 PDF 2.0 实现,因此即使可见结果相同,渲染出的字节仍会不同。如果你的测试针对确切的 PDF 字节进行断言,而不是针对渲染内容,请预期这些断言需要重新建立基准。建议的重新建立基准策略,请参阅 /integrations/tcpdf-compat/migration/。
2. 静默忽略方法 — 已记载的行为差异
标题为“2. 静默忽略方法 — 已记载的行为差异”的章节这 15 个方法会执行并产生输出,但至少有一个 TCPDF 参数虽然会为了源代码兼容而被接受,随后却会被忽略。这是迁移前最重要、也最需要阅读的一节,因为调用不会失败 — 它只是静默地比 TCPDF 原版少做一些事。
| TCPDF 方法 | 被忽略的参数 | 兼容的替代方案 |
|---|---|---|
Image() | type、link、align、resize、dpi、palign、ismask、imgmask、border、fitbox、hidden、fitonpage、alt、altimgs | NextPDF 的 image() 接受 file、x、y、width、height。如需制作可点击的图像,请先绘制图像,再在同一矩形范围上加入 Document::link()。不支持图像遮罩与替代图像。 |
writeHTML() | ln、fill、reseth、cell、align | NextPDF 的 writeHtml() 仅处理内容。如需版面控制,请通过现代 API 将 HTML 包在一个带定位的区块中。 |
writeHTMLCell() | border(字符串形式)、ln、fill、reseth、autopadding | 宽度、高度、位置与布尔值 border 会被采纳;更丰富的单元格版面没有对应项。 |
ImageEps() | link、useBoundingBox、align、palign、border、fitonpage、fixoutvals | 仅限位置与大小。 |
ImageSVG() | link、align、palign、border、fitonpage | 仅限位置与大小。 |
SetProtection() | mode(非零)、pubkeys(非空) | NextPDF 对标准处理器一律使用 AES-256。如需基于证书的加密,请使用适配器上公开的现代 setPublicKeyEncryption()(请参阅 /integrations/tcpdf-compat/security-and-operations/)。 |
Bookmark() | style、color、x、isNamedDest | 标题、层级与 y 坐标会被采纳。 |
setDestination() | page、x | 名称与 y 坐标会被采纳。 |
Link() | spaces | TCPDF 内部的空白追踪;引擎没有对应项。 |
Annotation() | Subtype 以外的 option 键、spaces | 类型、位置和文字会被采纳。 |
SetLineStyle() | width 以外的虚线样式(dash-pattern)细节 | 核心线条属性会被对应。 |
setAlpha() | 部分混合模式(blend-mode)映射 | 部分混合模式名称没有引擎对应项。 |
Polycurve() | 完整参数清单 | 在默认模式下为无作用(no-op);引擎没有对应项。 |
PieSectorXY() | 完整参数清单 | 部分映射(中心到外缘的线条有所不同)。 |
RoundedRectXY() | 各角独立的圆角半径 | 仅支持统一的圆角半径。 |
适配器如何呈现这些差异,取决于严格模式(strict mode)(请参阅 /integrations/tcpdf-compat/configuration/)。在严格模式关闭时(即向后兼容的默认设置),这些调用会静默降级。在严格模式开启时,每一个忽略了参数的调用都会抛出 TcpdfNotImplementedException,并附带被忽略参数的确切清单与一则迁移提示。严格模式是一项审计工具,并非生产环境设置。
严格模式的设计遵循一项原则:调用方必须能够察觉其意图何时未被采纳。 OWASP ASVS 5.0 §16.5.3 指出,应用程序应以优雅且安全的方式失败,并防止 fail-open 情况。 静默地遗失参数是一种开发体验陷阱,而非漏洞,但同样的明确失败(fail-explicitly)原则仍然适用。所列条款摘要位于页面前置数据的
citations中。
3. 未实现方法 — 空主体
标题为“3. 未实现方法 — 空主体”的章节有四个方法保留下来,使旧版源代码得以编译,但其主体不做任何事。在严格模式开启时,其中三个会抛出 TcpdfNotImplementedException。第四个(Open())是刻意设计的安全无作用方法,永远不会抛出异常,因为从旧版代码中移除它一律是安全的。
| TCPDF 方法 | 行为 | 替代方案 |
|---|---|---|
setSignature() | 无作用(不存储任何可操作内容)。在严格模式下会抛出异常。 | 数字签名需要商用版 NextPDF。请搭配 CertificateInfo 值对象使用现代签名 API — 请参阅 /integrations/tcpdf-compat/security-and-operations/. |
addEmptySignatureAppearance() | 无作用。在严格模式下会抛出异常。 | 与 setSignature() 相同的商用版限制。 |
endPage() | 无作用。在严格模式下会抛出异常。 | NextPDF 会自动管理页面生命周期。请移除此调用。 |
Open() | 安全的无作用。永远不会抛出异常。 | NextPDF 会自动开启文件。移除此调用一律是安全的。 |
通过此适配器,核心引擎并不提供签名功能。适配器公开了一个会委派给引擎的现代签名入口;基准签名支持受限于商用版。本文件不对任何版本的长期验证(long-term-validation)或加盖时间戳的签名配置文件做出任何宣称 — 确切且保守的说明请参阅 /integrations/tcpdf-compat/security-and-operations/。
4. 不适用方法
标题为“4. 不适用方法”的章节有七个 TCPDF 方法对 PDF 输出没有任何作用,已刻意排除。调用它们是无害的。
| TCPDF 方法 | 排除原因 |
|---|---|
setDocCreationTimestamp() / setDocModificationTimestamp() | 状态保存在适配器上,但未接入文档的 XMP 元数据。输出中不可见。 |
setSRGBmode() | NextPDF 的色彩管理与此标志无关。 |
setPDFVersion() | NextPDF 会根据其 conformance/output 配置文件选择 PDF 版本;没有直接的设置方法(setter)。适配器会发出一则通知并继续执行。 |
setDocInfoUnicode() | NextPDF 一律使用 Unicode;此标志按设计为无作用。 |
setDefaultMonospacedFont() | 引擎没有对应项;改用 HTML/CSS 样式应用。 |
setFontSubsetting() | NextPDF 一律会对嵌入字体进行子集化(subset);此标志实际上始终开启。 |
PDF 版本由引擎固定决定。输出会以 PDF 2.0(ISO 32000-2)写出。ISO 32000-2 §7.5.2 规定,符合要求的写入器应将文档版本 — 在文件头或目录的 Version 项中 — 标示为 2.0。它也规定,保存时不得将文档版本降至较旧的版本。这与适配器的行为一致:诸如 setPDFVersion('1.4') 之类的调用,无法通过此适配器将输出降级为较旧的 PDF 版本。所列条款摘要位于页面前置数据的 citations 中。
5. 现代 API 偏移方法
标题为“5. 现代 API 偏移方法”的章节有十七个来自 NextPDF 核心 v5.1+ 的方法在适配器上公开(trait AdaptsDriftV51),使混用 TCPDF API 与现代 API 的代码仍能编译。这些方法没有对应的 TCPDF 6.x 方法。示例:getWarnings()、hasWarnings()、embedFileFromString()、enableBiDi()、beginTag() / endTag()、enableLinearization()、useAesGcm()、useDocumentMac()、setConformanceMode()。请将这些视为现代 API,而非 TCPDF 兼容性契约的一部分。
6. 弃用与替代指引
标题为“6. 弃用与替代指引”的章节| 如果你的代码调用了… | 状态 | 改为这样做 |
|---|---|---|
Error() | 行为已变更(已强化) | TCPDF 的 die() 已改为抛出 RuntimeException。请以 try/catch 包裹有风险的调用;不要依赖进程终止。 |
setPDFVersion() | 不适用 | 移除。输出一律为 PDF 2.0。 |
setUserRights() | 在 PDF 2.0 中已弃用 | 移除。此调用会发出一则 E_USER_DEPRECATED 通知并予以忽略。 |
setSignature() | 核心中未实现 | 请在商用版上迁移到现代签名 API。 |
带有额外参数的 Image(...) | 静默忽略 | 精简为 file、x、y、w、h;可点击的图像请加入 Document::link()。 |
endPage() / Open() | 未实现 / 无作用 | 移除。 |
7. 安全迁移步骤
标题为“7. 安全迁移步骤”的章节- 安装软件包,并在不变更代码的情况下,用你既有的测试套件对适配器执行测试 — 请参阅 /integrations/tcpdf-compat/install/ 与 /integrations/tcpdf-compat/quickstart/.
- 在专门的审计运行(非生产环境)中启用严格模式:
$pdf->setStrictMode(true);。收集每一个TcpdfNotImplementedException。每一个都会指出被忽略参数的确切清单,并提供一则迁移提示。 - 对每一处抛出位置,选择:舍弃被忽略的参数,或通过
$pdf->getDocument()将该调用迁移到现代 API。 - 对任何针对确切 PDF 字节进行断言的测试重新建立基准;改为针对渲染内容或结构属性进行断言。
- 关闭严格模式,并部署已审计的代码路径。保留一个定期运行的严格模式 CI 作业,以便在你重构时拦截退化。
含代码的完整流程:/integrations/tcpdf-compat/migration/.
另请参阅
标题为“另请参阅”的章节docs/TCPDF_COVERAGE.md— 具权威性、经测试验证的覆盖范围矩阵(仓库内)- /integrations/tcpdf-compat/migration/ — 端到端的 TCPDF 至 NextPDF 迁移策略
- /integrations/tcpdf-compat/configuration/ — 严格模式与适配器设定
- /integrations/tcpdf-compat/security-and-operations/ — 加密与签名状态
- /integrations/tcpdf-compat/integration/ — 将适配器接入应用程序
- /integrations/tcpdf-compat/boot-and-discovery/ — 类别名注册与门面(facade)公开