從 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 對應表。