← Writing

PHP: TCPDF Library in Laravel

前言 總覺得跟 pdf 功能十分有緣分,先前在製作 READMEE 的專案時,有運用到 jspdf 這個前端的 pdf 套件,這次在工作上要使用後端的方式來處理,這次要來介紹 TCPDF! TCPDF 簡介 TCPDF 是一個用於生成 PDF 文件的免費且開源的 PHP 類別,而且也是唯一基於 PH...

laravelphptcpdf

前言

總覺得跟 pdf 功能十分有緣分,先前在製作 READMEE 的專案時,有運用到 jspdf 這個前端的 pdf 套件,這次在工作上要使用後端的方式來處理,這次要來介紹 TCPDF!

TCPDF 簡介

TCPDF 是一個用於生成 PDF 文件的免費且開源的 PHP 類別,而且也是唯一基於 PHP 的函式庫並完全支援 UTF-8 Unicode 和從右到左的語言。在 2009 年,TCPDF 是 SourceForge 上超過 200,000 個項目中最活躍的之一(於 2010 年 4 月 3 日排名第 6)。

特色

在使用上,TCPDF 能夠在 PHP 應用程式中生成高度自定義和具有豐富內容的 PDF 文件,而無需依賴外部的程式庫,像是:

  • PDF 文件生成: TCPDF 可以生成 PDF 文件,用於呈現文檔、報告、表格等內容。

  • 頁面格式支援: 提供對所有標準頁面格式、自定義頁面格式、自定義邊界和度量單位的支援。

  • 文字編碼支援: 完整支援 UTF-8 Unicode 和從右到左的語言。

  • 字型支援: 支援多種字型格式,包括 TrueTypeUnicode、OpenTypeUnicode、TrueType、OpenType、Type 1 和 CID-0 字型,並具有字型子集功能。

  • 圖片和圖形處理: 能夠處理圖片、圖形(如幾何圖形),原生支援 JPEG、PNG 和 SVG 圖片,以及其他圖片格式透過 GD Graphics Library 和 ImageMagick 的支援。

  • 條碼生成: 提供生成各種條碼(1D 和 2D)的功能,包括 CODE 39、CODE 128、QRcode 等。

  • 顏色和透明度: 支援不同的色彩模式,包括灰度、RGB、CMYK、Spot Colors,以及處理透明度。

  • 頁面管理: 包括自動管理頁首和頁尾、自動分頁、換行和文本對齊等功能。

  • 安全性: 提供文件加密高達 256 位和數位簽名認證。

  • 其他功能: 包括註釋、文本渲染模式、多列模式、書籤和內容表、XOBject 模板、PDF/A-1b(ISO 19005-1:2005)支援等。


TCPDF 安裝

在使用之前,要先來安裝 TCPDF 到應用程式裡,這次在 GitHub 找到以 TCPDF 為基底的 open source: elibyy/tcpdf-laravel

可以透過 packagist 找自己想要的 package,先前有找到 dompdf 但是實作起來發現支援中文字體的功能稍嫌不足,找了很多辦法始終沒有效果,因此轉往 TCPDF 來實作!

透過 composer 來安裝 elibyy/tcpdf-laravel 套件

可以透過兩種方式:

  1. 在 terminal 輸入以下指令: composer require elibyy/tcpdf-laravel

  2. composer.json 的 require 裡寫下,"elibyy/tcpdf-laravel": "^9.0"

要記得 JSON 格式要寫對

{
    "require": {
        "elibyy/tcpdf-laravel": "^9.0"
    }
}

TCPDF 引入與使用

安裝完成後,就要來實際寫進 app 裡囉!

建立 Route

在 /routes 資料夾的 web.php 新增一條路徑。

...
use App\Http\Controllers\PDFController;

Route::get('pdf', [PDFController::class,'index']);
...

建立 Controller

在 Laravel 裡,要傳遞資料給 blade 來渲染畫面,就要建立 Controller 去傳遞! 因此,建立 Controller 來引入 TCPDF 功能並使用:

在 terminal 輸入以下指令: php artisan make:controller PDFController

指令會在 app/Http/Controllers 資料夾裡出現 PDFController,並在裡頭寫下方法:

<?php

namespace App\Http\Controllers;

use Elibyy\TCPDF\Facades\TCPDF;

class PDFController extends Controller
{
    public function index()
    {
        $filename = 'sample.pdf';
  
        $data = [
            'title' => 'To Create PDF Files Using TCPDF Library'
        ];
  
        $html = view()->make('pdf', $data)->render();
  
        $pdf = new TCPDF;
          
        $pdf::SetTitle('Generate PDF Using Laravel Library');
        $pdf::AddPage();
        $pdf::writeHTML($html, true, false, true, false, '');
  
        $pdf::Output(public_path($filename), 'F');
  
        return response()->download(public_path($filename));
    }
}

如果有使用 Livewire 作為 Controller 的話,要注意 line 25-27 方法要改為:

       return response()->streamDownload(
           fn () => $pdf::Output(public_path($filename), 'F'),
           $filename
       );

建立 Blade

接著,在 /resources/views 資料夾建立一個 pdf.blade.php,用以呈現 pdf 的畫面。

<!DOCTYPE html>
<html>

<head>
    <title>To Create PDF Files Using TCPDF Library</title>
</head>

<body>
    <h1 style="color:blue;">{!! $title !!}</h1>
</body>

</html>

以上設定完成之後,就可以在 terminal 輸入:php artisan serve 開啟 server, 當你連到 http://127.0.0.1:8000/pdf 路徑時,就會自動下載一份名為 sample.pdf 的檔案!


TCPDF 常見方法與參數說明

建立新的 PDF 物件

$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);

  1. PDF_PAGE_ORIENTATION 用於設置頁面方向的參數。通常,可以使用 P(直向)或 L(橫向),空值則自動判斷,預設為 P(直向)。

  2. PDF_UNIT 用於設置頁面單位。在 PDF 中,頁面的大小和位置可以使用不同的單位來測量,例如,pt、mm(預設)、cm、in 等。

  3. PDF_PAGE_FORMAT 用於設置頁面格式的參數。通常是一個字串,指定了頁面的標準大小,如 A4(預設)、Letter 等。例如,PDF_PAGE_FORMAT = 'A4' 將設置頁面格式為 A4 大小。

  4. true 用於啟用或禁用自動頁面設置。當設置為 true 時,TCPDF 將自動調整頁面大小以適應內容。

  5. 'UTF-8' 用於設置文本編碼。UTF-8 是一種廣泛使用的字符編碼,支持多種語言。

  6. false 用於指定是否使用純文本模式。如果設置為 true,則 PDF 將以純文本模式創建。

常見方法

以下透過建立好的 $pdf 來以實例方法調用 TCPDF Library:

TCPDF::setPrintHeader( $val = true ) / TCPDF::setPrintFooter( $val = true )

  • 設定頁首頁尾
$pdf->setPrintHeader(false); //不要頁首
$pdf->setPrintFooter(false); //不要頁尾

TCPDF::SetFont( $family, $style = '', $size = null, $fontfile = '', $subset = 'default', $out = true )

  • 設定字型
$pdf->SetFont( $family, $style = '', $size = null, $fontfile = '', $subset = 'default', $out = true )
  • 參數說明

    $family 用於指定字型的整體風格,例如 Serif(襯線體)、Sans-serif(無襯線體)等。常見的值包括 'times'、'helvetica'、'courier' 等,也可以是自定義字型的名稱。

    $style 用於字型的風格,包括 'B'(粗體)、'I'(斜體)、'U'(底線)等。預設值為空字串,表示普通風格。多個風格可以組合使用,例如 'BIU' 表示粗體、斜體和底線。

    $size 用於字型的大小。如果設置為 null,則保持當前字型大小。

    $fontfile 用於指定字型文件的路徑。如果指定字型文件,則使用該文件作為字型。如果沒有提供,則使用 TCPDF 預設的字型。可以是 TrueType 字型文件 (.ttf) 或其他支援的字型格式。

    $subset 用於設置是否生成字型子集的參數。字型子集只包含實際使用到的字符,有助於減小生成的 PDF 文件大小。預設值為 'default',表示使用 TCPDF 的預設設置。也可以設置為 'full'(生成全部字符的子集)或 'simple'(只包含ASCII字符的子集)。

    $out 用於是否輸出該設定。如果設置為 false,則只是設定當前字型的參數,不會將其應用於生成的 PDF。預設值為 true

TCPDF::SetAutoPageBreak( $auto, $margin )

  • 設定自動分頁
$pdf->SetAutoPageBreak( $auto, $margin );
  • 參數說明

    $auto (boolean) 用於啟用或禁用自動分頁。如果設置為 true,則 TCPDF 將根據內容自動決定何時換頁。如果設置為 false,則需要手動控制分頁。

    $margin 是一個數值,表示當新頁面開始時,頁面底部應該有多少空白(邊界)。通常,這個值是以點(point)為單位的,點是印刷行業中常用的長度單位之一。

TCPDF::AddPage( $orientation = '', $format = '', $keepmargins = false, $tocpage = false )

  • 新增分頁
$pdf->AddPage( $orientation = '',  $format = '',  $keepmargins = false,  $tocpage = false )
  • 參數說明

    $orientation 用於頁面的方向,可以是 'P'(直向,預設值)或 'L'(橫向)。如果不指定,則使用預設值。

    $format 用於頁面的格式參數,表示頁面的標準大小。常見的值包括 'A4'(預設值)、'Letter'、'Legal' 等。如果不指定,則使用預設值。

    $keepmargins (boolean) 用於指定是否保留當前頁面的邊距設置。如果設置為 true,則新頁面將繼承當前頁面的邊距。如果設置為 false(預設值),則新頁面的邊距將使用預設值。

    $tocpage (boolean) 用於指定新頁面是否應該包含在文檔的目錄(Table Of Contents)中。如果設置為 true,則將在目錄中添加對新頁面的引用。如果設置為 false(預設值),則新頁面不會包含在目錄中。

TCPDF::writeHTML( $html, $ln = true, $fill = false, $reseth = false, $cell = false, $align = '' )

  • 用於將包含 HTML 內容的字符串寫入 PDF 文件
$pdf->writeHTML( $html,  $ln = true,  $fill = false,  $reseth = false,  $cell = false,  $align = '' )
  • 參數說明

    $html 用於將帶有基本標籤的 HTML 代碼傳遞給這個方法,有支援的網頁標籤:a, b, blockquote, br, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, img, li, ol, p, pre, small, span, strong, sub, sup, table, tcpdf, td, th, thead, tr, tt, u, ul。

    屬性一定要用雙引號

    $ln (boolean) 是否在內容的末尾換行。如果設置為 true(預設值),在內容結束時會換行到下一行;如果設置為 false,則不會換行。

    $fill (boolean) 是否填充內容區域的背景。如果設置為 true,則內容的區域將被填充;如果設置為 false(預設值),則不會填充。

    $reseth (boolean) 是否重置當前頁面的高度。如果設置為 true,則在寫入內容之前,將重置頁面的高度。預設值是 false

    $cell (boolean) 是否在內容周圍創建一個儲存格(cell)。如果設置為 true,內容將被放置在一個儲存格中;如果設置為 false(預設值),內容將被放置在頁面上,忽略儲存格的邊界。

    $align 是一個字串,表示內容的對齊方式。可以是 'L'(左對齊)、'C'(居中對齊)、'R'(右對齊)等。預設值是空字符串,表示沒有指定對齊方式。

TCPDF::Output( $name = 'doc.pdf', $dest = 'I' )

  • 用於生成並輸出 PDF 文件
$pdf->Output( $name = 'doc.pdf',  $dest = 'I' )
  • 參數說明

    $name = 'doc.pdf' 生成的 PDF 文件的名稱。

    $dest = 'I' 指定如何處理生成的文件的參數。預設為 'I',表示直接在瀏覽器中顯示(inline)。

    其他還有: 'D' - 將文件發送到瀏覽器,並使用提供的名稱強制進行文件下載。 'F' - 將文件保存到本地文件系統(local server)。 'S' - 以字串形式返回文件(文件名將被忽略)。 'FI' - 以 streaming* 方式寫入本地文件,不是立即顯示在瀏覽器中。用於在伺服器上保存生成的文件,而不需要立即顯示給用戶。 'FD' - 以 streaming* 方式將文件提供給瀏覽器進行下載,生成的 PDF 文件將被發送到瀏覽器,讓用戶可以選擇下載文件。這對於生成的文件不需要保存在伺服器上,而是由用戶自行下載時很有用。 'E' - 會生成 base64 編碼的字串,適合用作電子郵件的附件。

    補充: *streaming 是一種在處理數據時,不需要將整個數據集一次性讀取或寫入的方法。數據被分割成小的部分,逐個處理,這樣可以節省內存,提高效率,特別適用於處理大型數據集或文件。


TCPDF 設定排版方法

  • TCPDF 有三種方式可以自定義排版與整體結構: TCPDF::Cell() - 繪製單行文本區域
$pdf->Cell( $w,  $h,  $txt = '',  $border,  $ln,  $align = '',  $fill = false,  $link = '',  $stretch,  $ignore_min_height = false,  $calign = 'T',  $valign = 'M' )

TCPDF::MultiCell() - 繪製多行文本區域

$pdf->MultiCell( $w,  $h,  $txt,  $border,  $align = 'J',  $fill = false,  $ln = 1,  $x = '',  $y = '',  $reseth = true,  $stretch,  $ishtml = false,  $autopadding = true,  $maxh,  $valign = 'T',  $fitcell = false )

TCPDF::writeHTMLCell() - 以 HTML 格式繪製文本區域

$pdf->writeHTMLCell( $w,  $h,  $x,  $y,  $html = '',  $border,  $ln,  $fill = false,  $reseth = true,  $align = '',  $autopadding = true )
  • 共同的參數說明

    $w 寬度。

    ➢ **$h:**高度。

    $border 用於設定文本區域的邊框,可以是 0、1、2、4、8 或其組合。

    $ln 是一個整數,表示應該在哪裡進行下一個元素的放置。

    可選值有: 0 - 右來的位置(預設值) 1 - 下一行的開頭 2 - 在當前行的下一頁的開頭

    $fill (boolean) 表示是否填充文本區域的背景。如果設置為 true,則填充,否則不填充。預設為 false

    $reseth (boolean) 表示是否重置當前字型。默認為 true


  • TCPDF::Cell() 專屬參數與 TCPDF::MultiCell() 專屬參數:

    $txt 在文本區域中顯示的文本。

    $align 用於設定文本在文本區域中的對齊方式。

    可選值有: 'L' - 左對齊 'C' - 居中對齊 'R' - 右對齊 'J' - 兩端對齊(預設)

    $x 文本區域的左上角的 x 軸位置。

    $y 文本區域的左上角的 y 軸位置。

  • TCPDF::MultiCell() 專屬參數:

    $stretch (boolean) 表示是否自動拉伸文字以填充整個多行文本區域。預設為 false

  • TCPDF::writeHTMLCell() 專屬參數:

    $html 包含 HTML 內容的字串,也就是要在文本區域中顯示的 HTML。

    $autopadding (boolean) 表示是否啟用自動填充。如果設置為 true,則根據字型實際高度動態調整 HTML 文本區域的高度。


TCPDF 還有很多可以設定的方式,仔細去看發現整體的方法真的有很多種也有支援的中文字型真的友善許多!可以透過 Dev Resources - TCPDF methods 去查找方法,如果看 TCPDF 的原始文件真的會看到心很累哈哈哈,以上就是這次工作上遇到的套件學習整理,給自己一個鼓勵 ୧ʕ•̀ᴥ•́ʔ୨ (耶~)


參考資料

Tad 教材網 TCPDF筆記 Dev Resources - TCPDF methods