Skip to content

从 TCPDF 迁移

本指南协助您将现有项目从 TCPDF(tecnickcom/tcpdf)迁移至 TCPDF-Next。虽然 TCPDF-Next 是完全重写的版本,并非直接替换,但通过兼容性层与 API 映射表,迁移过程相当直接。

关键差异

特性TCPDFTCPDF-Next
PHP 版本5.3+8.5+
PDF 版本PDF 1.7PDF 2.0
架构单一巨型类17 个模块化命名空间
API 风格过程式方法流畅构建器模式
类型安全严格类型、枚举、只读
加密RC4、AES-128、AES-256仅 AES-256(PDF 2.0)
签名基础 PKCS#7PAdES B-B 至 B-LTA
PDF/APDF/A-1b(部分)PDF/A-4(完整)
交叉引用传统 xref 表格交叉引用流
字体处理内部格式,自动加载标准 TTF/OTF,显式注册
HTML 解析内置(有限)DOM 引擎(改进版)
依赖包零(相同)

迁移策略

选项一:使用兼容性层渐进迁移

TCPDF-Next 提供一个兼容性层,可将大多数 TCPDF 方法调用映射至新 API,让您能增量式迁移。

bash
composer require yeee-fang/tcpdf-next
php
// 步骤 1:将 TCPDF 类替换为兼容性包装器
// 迁移前:
use TCPDF;

// 迁移后:
use YeeeFang\TcpdfNext\Compat\TcpdfCompat as TCPDF;

兼容性层支持约 80% 的 TCPDF 公开方法。不支持的方法会抛出 DeprecatedMethodException,并提供现代替代方案的指引。

WARNING

兼容性层仅作为迁移辅助工具,并非永久解决方案。它会增加额外开销,且无法使用 TCPDF-Next 的高级功能(PAdES 签名、PDF/A-4 等)。请规划迁移至原生 API。

选项二:完整迁移(建议方式)

将 PDF 生成代码重写为使用 TCPDF-Next 原生 API。这能使用所有功能并获得最佳性能。

逐步迁移

步骤 1:更新包需求

json
{
    "require": {
        "php": "^8.5",
        "yeee-fang/tcpdf-next": "^1.0"
    }
}
bash
composer remove tecnickcom/tcpdf
composer require yeee-fang/tcpdf-next

步骤 2:替换文档创建

TCPDF(迁移前):

php
$pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false);
$pdf->SetCreator('My App');
$pdf->SetAuthor('John Doe');
$pdf->SetTitle('Invoice #12345');
$pdf->SetSubject('Monthly Invoice');
$pdf->SetKeywords('invoice, payment, monthly');
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->SetMargins(15, 15, 15);
$pdf->SetAutoPageBreak(true, 15);
$pdf->AddPage();

TCPDF-Next(迁移后):

php
use YeeeFang\TcpdfNext\Document\PdfDocument;
use YeeeFang\TcpdfNext\Document\PageFormat;
use YeeeFang\TcpdfNext\Document\Orientation;
use YeeeFang\TcpdfNext\Document\Margins;

$pdf = PdfDocument::create()
    ->setCreator('My App')
    ->setAuthor('John Doe')
    ->setTitle('Invoice #12345')
    ->setSubject('Monthly Invoice')
    ->setKeywords(['invoice', 'payment', 'monthly'])
    ->setPageFormat(PageFormat::A4)
    ->setOrientation(Orientation::PORTRAIT)
    ->setMargins(Margins::uniform(15))
    ->setAutoPageBreak(true, bottomMargin: 15)
    ->build();

$page = $pdf->addPage();

步骤 3:替换字体处理

TCPDF(迁移前):

php
$pdf->SetFont('helvetica', 'B', 14);
$pdf->SetFont('times', '', 12);

// 自定义字体
$fontname = TCPDF_FONTS::addTTFfont('/path/to/custom.ttf', 'TrueTypeUnicode');
$pdf->SetFont($fontname, '', 10);

TCPDF-Next(迁移后):

php
// 内置字体(PDF/A 模式下自动嵌入)
$page->setFont('Helvetica', size: 14, style: FontStyle::BOLD);
$page->setFont('Times', size: 12);

// 自定义字体
$pdf->getFontManager()->registerFont('/path/to/custom.ttf', 'CustomFont');
$page->setFont('CustomFont', size: 10);

步骤 4:替换文字与绘图操作

TCPDF(迁移前):

php
$pdf->SetXY(15, 50);
$pdf->Cell(180, 10, 'Invoice #12345', 1, 1, 'C', false, '', 0, false, 'T', 'M');
$pdf->MultiCell(180, 10, 'Long description text...', 0, 'L', false, 1);
$pdf->Ln(10);

// 绘图
$pdf->SetDrawColor(0, 0, 0);
$pdf->SetFillColor(200, 200, 200);
$pdf->Rect(15, 100, 180, 0.5, 'F');
$pdf->Line(15, 110, 195, 110);

TCPDF-Next(迁移后):

php
use YeeeFang\TcpdfNext\Color\Color;
use YeeeFang\TcpdfNext\Text\Alignment;

// Cell 映射
$page->addText('Invoice #12345')
    ->setPosition(15, 50)
    ->setSize(180, 10)
    ->setAlignment(Alignment::CENTER)
    ->setBorder(true)
    ->setVerticalAlignment(VerticalAlignment::MIDDLE);

// MultiCell 映射
$page->addParagraph('Long description text...')
    ->setPosition(15, 60)
    ->setWidth(180)
    ->setAlignment(Alignment::LEFT);

// 绘图
$canvas = $page->getCanvas();
$canvas->setFillColor(Color::rgb(200, 200, 200))
    ->drawRect(15, 100, 180, 0.5)
    ->fill();

$canvas->setStrokeColor(Color::black())
    ->drawLine(15, 110, 195, 110)
    ->stroke();

步骤 5:替换图片处理

TCPDF(迁移前):

php
$pdf->Image('/path/to/logo.png', 15, 10, 40, 0, 'PNG');
$pdf->Image('@' . $binaryData, 15, 60, 40);

TCPDF-Next(迁移后):

php
// 从文件
$page->addImage('/path/to/logo.png')
    ->setPosition(15, 10)
    ->setWidth(40);

// 从二进制数据
$page->addImage($binaryData, format: ImageFormat::PNG)
    ->setPosition(15, 60)
    ->setWidth(40);

步骤 6:替换 HTML 输出

TCPDF(迁移前):

php
$html = '<h1>Invoice</h1><table><tr><td>Item</td><td>Price</td></tr></table>';
$pdf->writeHTML($html, true, false, true, false, '');
$pdf->writeHTMLCell(180, 0, 15, 50, $html, 0, 1, false, true, 'L', true);

TCPDF-Next(迁移后):

php
use YeeeFang\TcpdfNext\Html\HtmlRenderer;

$renderer = new HtmlRenderer($pdf);

// 简单 HTML 写入
$renderer->writeHtml('<h1>Invoice</h1><table><tr><td>Item</td><td>Price</td></tr></table>');

// 在指定区域写入 HTML
$renderer->writeHtml($html, position: [15, 50], width: 180);

步骤 7:替换条码生成

TCPDF(迁移前):

php
$pdf->write1DBarcode('ABC-123', 'C128', 15, 200, 80, 20);
$pdf->write2DBarcode('https://example.com', 'QRCODE,H', 15, 230, 30, 30);

TCPDF-Next(迁移后):

php
use YeeeFang\TcpdfNext\Barcode\BarcodeFactory;

$code128 = BarcodeFactory::code128('ABC-123');
$page->addBarcode($code128)
    ->setPosition(15, 200)
    ->setSize(80, 20);

$qrCode = BarcodeFactory::qrCode('https://example.com', errorCorrection: 'H');
$page->addBarcode($qrCode)
    ->setPosition(15, 230)
    ->setSize(30, 30);

步骤 8:替换输出方式

TCPDF(迁移前):

php
$pdf->Output('/path/to/output.pdf', 'F'); // 保存至文件
$pdf->Output('invoice.pdf', 'D');          // 强制下载
$pdf->Output('invoice.pdf', 'I');          // 内嵌显示
$content = $pdf->Output('', 'S');          // 以字符串返回

TCPDF-Next(迁移后):

php
// 保存至文件
$pdf->save('/path/to/output.pdf');

// 以字符串取得
$bytes = $pdf->toString();

// 在 Web 环境中(Laravel 示例)
return response($pdf->toString(), 200, [
    'Content-Type' => 'application/pdf',
    'Content-Disposition' => 'attachment; filename="invoice.pdf"',
]);

步骤 9:替换加密

TCPDF(迁移前):

php
$pdf->SetProtection(['print', 'copy'], 'user-password', 'owner-password', 3);

TCPDF-Next(迁移后):

php
use YeeeFang\TcpdfNext\Encryption\EncryptionAlgorithm;
use YeeeFang\TcpdfNext\Encryption\Permissions;

$pdf->setEncryption()
    ->setAlgorithm(EncryptionAlgorithm::AES256)
    ->setUserPassword('user-password')
    ->setOwnerPassword('owner-password')
    ->setPermissions(Permissions::PRINT_HIGH_QUALITY | Permissions::COPY)
    ->apply();

步骤 10:新增数字签名(新功能)

TCPDF 的签名支持非常有限。TCPDF-Next 新增完整的 PAdES 支持:

php
use YeeeFang\TcpdfNext\Signature\PdfSigner;
use YeeeFang\TcpdfNext\Signature\SignatureLevel;

$signer = new PdfSigner($pdf);
$signer->setCertificate($cert, $privateKey)
    ->setLevel(SignatureLevel::PAdES_B_LTA)
    ->setTimestampServer('https://timestamp.digicert.com')
    ->setReason('Invoice approval')
    ->sign();

常见迁移问题

问题:自定义 TCPDF 字体

TCPDF 使用自有的二进制字体格式(.php + .z 文件)。TCPDF-Next 直接使用标准 TTF/OTF 文件。

解决方式: 以原始 TTF/OTF 文件替换 TCPDF 字体文件:

php
// 迁移前:TCPDF 二进制字体
$pdf->SetFont('dejavusans', '', 12);

// 迁移后:注册原始 TTF 文件
$pdf->getFontManager()->registerFont('/path/to/DejaVuSans.ttf', 'DejaVuSans');
$page->setFont('DejaVuSans', size: 12);

问题:页眉/页脚回调

TCPDF 使用方法覆写来实现页眉页脚。TCPDF-Next 使用事件回调:

php
// 迁移前(TCPDF):继承类
class MyPDF extends TCPDF {
    public function Header() { /* ... */ }
    public function Footer() { /* ... */ }
}

// 迁移后(TCPDF-Next):使用回调
$pdf->onPageHeader(function (Page $page, int $pageNumber) {
    $page->addText('Company Name')
        ->setPosition(15, 10)
        ->setFont('Helvetica', size: 8);
});

$pdf->onPageFooter(function (Page $page, int $pageNumber, int $totalPages) {
    $page->addText("Page {$pageNumber} of {$totalPages}")
        ->setPosition(15, 282)
        ->setFont('Helvetica', size: 8)
        ->setAlignment(Alignment::CENTER);
});

破坏性变更检查清单

迁移时请逐项确认以下变更:

  • [ ] PHP 版本升级至 8.5+
  • [ ] 所有 TCPDF 命名空间已更换为 YeeeFang\TcpdfNext\*
  • [ ] 构造器参数已更新为构建器模式
  • [ ] PascalCase 方法名已更新为 camelCase(如 SetFontsetFont
  • [ ] 位置参数已更新为命名参数
  • [ ] 字体文件已从 TCPDF 二进制格式替换为 TTF/OTF
  • [ ] RC4 / AES-128 加密已更新为 AES-256
  • [ ] Output() 调用已替换为 save() / toString()
  • [ ] 页眉/页脚子类已替换为回调
  • [ ] K_PATH_* 常量已移除,使用构建器方法配置
  • [ ] tcpdf_config.php 已移除,使用 SecurityConfig 类配置

完整 API 映射表

如需每个 TCPDF 方法映射至 TCPDF-Next 等价方法的完整对照,请参阅 API 映射表

延伸阅读

以 LGPL-3.0-or-later 许可证发布。