跳转到内容

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 偏移方法17NextPDF v5.1+ 在适配器上公开的 Document 方法,使混用 API 的代码得以编译。没有对应的 TCPDF 6.x 方法。

这些数字来自 docs/TCPDF_COVERAGE.md §Summary。该矩阵由 tests/Unit/Compat/Tcpdf/TcpdfApiDriftTest.phptests/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。

有九十四个方法会直接映射到底层的 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、altimgsNextPDF 的 image() 接受 file、x、y、width、height。如需制作可点击的图像,请先绘制图像,再在同一矩形范围上加入 Document::link()。不支持图像遮罩与替代图像。
writeHTML()ln、fill、reseth、cell、alignNextPDF 的 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()spacesTCPDF 内部的空白追踪;引擎没有对应项。
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 中。

有四个方法保留下来,使旧版源代码得以编译,但其主体不做任何事。在严格模式开启时,其中三个会抛出 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/。

有七个 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 中。

有十七个来自 NextPDF 核心 v5.1+ 的方法在适配器上公开(trait AdaptsDriftV51),使混用 TCPDF API 与现代 API 的代码仍能编译。这些方法没有对应的 TCPDF 6.x 方法。示例:getWarnings()hasWarnings()embedFileFromString()enableBiDi()beginTag() / endTag()enableLinearization()useAesGcm()useDocumentMac()setConformanceMode()。请将这些视为现代 API,而非 TCPDF 兼容性契约的一部分。

如果你的代码调用了…状态改为这样做
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()未实现 / 无作用移除。
  1. 安装软件包,并在不变更代码的情况下,用你既有的测试套件对适配器执行测试 — 请参阅 /integrations/tcpdf-compat/install/ 与 /integrations/tcpdf-compat/quickstart/.
  2. 在专门的审计运行(非生产环境)中启用严格模式:$pdf->setStrictMode(true);。收集每一个 TcpdfNotImplementedException。每一个都会指出被忽略参数的确切清单,并提供一则迁移提示。
  3. 对每一处抛出位置,选择:舍弃被忽略的参数,或通过 $pdf->getDocument() 将该调用迁移到现代 API。
  4. 对任何针对确切 PDF 字节进行断言的测试重新建立基准;改为针对渲染内容或结构属性进行断言。
  5. 关闭严格模式,并部署已审计的代码路径。保留一个定期运行的严格模式 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)公开