从 TCPDF 迁移
本指南协助您将现有项目从 TCPDF(tecnickcom/tcpdf)迁移至 TCPDF-Next。虽然 TCPDF-Next 是完全重写的版本,并非直接替换,但通过兼容性层与 API 映射表,迁移过程相当直接。
关键差异
| 特性 | TCPDF | TCPDF-Next |
|---|---|---|
| PHP 版本 | 5.3+ | 8.5+ |
| PDF 版本 | PDF 1.7 | PDF 2.0 |
| 架构 | 单一巨型类 | 17 个模块化命名空间 |
| API 风格 | 过程式方法 | 流畅构建器模式 |
| 类型安全 | 无 | 严格类型、枚举、只读 |
| 加密 | RC4、AES-128、AES-256 | 仅 AES-256(PDF 2.0) |
| 签名 | 基础 PKCS#7 | PAdES B-B 至 B-LTA |
| PDF/A | PDF/A-1b(部分) | PDF/A-4(完整) |
| 交叉引用 | 传统 xref 表格 | 交叉引用流 |
| 字体处理 | 内部格式,自动加载 | 标准 TTF/OTF,显式注册 |
| HTML 解析 | 内置(有限) | DOM 引擎(改进版) |
| 依赖包 | 零 | 零(相同) |
迁移策略
选项一:使用兼容性层渐进迁移
TCPDF-Next 提供一个兼容性层,可将大多数 TCPDF 方法调用映射至新 API,让您能增量式迁移。
composer require yeee-fang/tcpdf-next// 步骤 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:更新包需求
{
"require": {
"php": "^8.5",
"yeee-fang/tcpdf-next": "^1.0"
}
}composer remove tecnickcom/tcpdf
composer require yeee-fang/tcpdf-next步骤 2:替换文档创建
TCPDF(迁移前):
$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(迁移后):
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(迁移前):
$pdf->SetFont('helvetica', 'B', 14);
$pdf->SetFont('times', '', 12);
// 自定义字体
$fontname = TCPDF_FONTS::addTTFfont('/path/to/custom.ttf', 'TrueTypeUnicode');
$pdf->SetFont($fontname, '', 10);TCPDF-Next(迁移后):
// 内置字体(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(迁移前):
$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(迁移后):
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(迁移前):
$pdf->Image('/path/to/logo.png', 15, 10, 40, 0, 'PNG');
$pdf->Image('@' . $binaryData, 15, 60, 40);TCPDF-Next(迁移后):
// 从文件
$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(迁移前):
$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(迁移后):
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(迁移前):
$pdf->write1DBarcode('ABC-123', 'C128', 15, 200, 80, 20);
$pdf->write2DBarcode('https://example.com', 'QRCODE,H', 15, 230, 30, 30);TCPDF-Next(迁移后):
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(迁移前):
$pdf->Output('/path/to/output.pdf', 'F'); // 保存至文件
$pdf->Output('invoice.pdf', 'D'); // 强制下载
$pdf->Output('invoice.pdf', 'I'); // 内嵌显示
$content = $pdf->Output('', 'S'); // 以字符串返回TCPDF-Next(迁移后):
// 保存至文件
$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(迁移前):
$pdf->SetProtection(['print', 'copy'], 'user-password', 'owner-password', 3);TCPDF-Next(迁移后):
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 支持:
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 字体文件:
// 迁移前:TCPDF 二进制字体
$pdf->SetFont('dejavusans', '', 12);
// 迁移后:注册原始 TTF 文件
$pdf->getFontManager()->registerFont('/path/to/DejaVuSans.ttf', 'DejaVuSans');
$page->setFont('DejaVuSans', size: 12);问题:页眉/页脚回调
TCPDF 使用方法覆写来实现页眉页脚。TCPDF-Next 使用事件回调:
// 迁移前(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(如
SetFont→setFont) - [ ] 位置参数已更新为命名参数
- [ ] 字体文件已从 TCPDF 二进制格式替换为 TTF/OTF
- [ ] RC4 / AES-128 加密已更新为 AES-256
- [ ]
Output()调用已替换为save()/toString() - [ ] 页眉/页脚子类已替换为回调
- [ ]
K_PATH_*常量已移除,使用构建器方法配置 - [ ]
tcpdf_config.php已移除,使用SecurityConfig类配置
完整 API 映射表
如需每个 TCPDF 方法映射至 TCPDF-Next 等价方法的完整对照,请参阅 API 映射表。