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:替换文档创建

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(); 
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:替换字体处理

php
$pdf->SetFont('helvetica', 'B', 14); 
$pdf->SetFont('times', '', 12); 
// 自定义字体
$fontname = TCPDF_FONTS::addTTFfont('/path/to/custom.ttf', 'TrueTypeUnicode'); 
$pdf->SetFont($fontname, '', 10); 
// 内置字体(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:替换图片处理

php
$pdf->Image('/path/to/logo.png', 15, 10, 40, 0, 'PNG'); 
$pdf->Image('@' . $binaryData, 15, 60, 40); 
// 从文件
$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:替换条码生成

php
$pdf->write1DBarcode('ABC-123', 'C128', 15, 200, 80, 20); 
$pdf->write2DBarcode('https://example.com', 'QRCODE,H', 15, 230, 30, 30); 
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:替换输出方式

php
$pdf->Output('/path/to/output.pdf', 'F'); // 保存至文件
$pdf->Output('invoice.pdf', 'D');          // 强制下载
$pdf->Output('invoice.pdf', 'I');          // 内嵌显示
$content = $pdf->Output('', 'S');          // 以字符串返回
// 保存至文件
$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:替换加密

php
$pdf->SetProtection(['print', 'copy'], 'user-password', 'owner-password', 3); 
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 许可证发布。