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 授權釋出。