進階功能
本頁涵蓋 Artisan 套件的進階類別:PDF 合併、樣式注入、截圖擷取,以及 Chrome 程序管理與錯誤處理。
PDF 合併(PdfMerger)
PdfMerger 將多份 PDF 檔案合併為單一文件,支援檔案路徑與二進位字串兩種輸入方式:
php
use Yeeefang\TcpdfNext\Artisan\PdfMerger;
PdfMerger::create()
->add('/path/to/cover.pdf')
->add('/path/to/chapter1.pdf')
->add('/path/to/chapter2.pdf')
->save('/path/to/merged.pdf');從二進位字串合併
搭配 HtmlRenderer::toString() 使用,可在記憶體中完成渲染與合併,無需寫入暫存檔案:
php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
use Yeeefang\TcpdfNext\Artisan\PdfMerger;
$renderer = HtmlRenderer::create();
$cover = $renderer->loadHtml($coverHtml)->toString();
$content = $renderer->loadHtml($contentHtml)->toString();
PdfMerger::create()
->addBinary($cover)
->addBinary($content)
->save('/path/to/final.pdf');樣式注入(StyleInjector)
StyleInjector 在 Chrome 渲染之前,將額外的 CSS 注入到 HTML 中。適用於在不修改模板的情況下覆寫樣式:
php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
use Yeeefang\TcpdfNext\Artisan\StyleInjector;
$injector = StyleInjector::create()
->add('body { font-family: "Noto Sans TC", sans-serif; }')
->add('@page { size: A4 landscape; }')
->addFile('/path/to/print-overrides.css');
HtmlRenderer::create()
->withStyleInjector($injector)
->loadUrl('https://app.example.com/dashboard')
->save('/tmp/dashboard.pdf');TIP
注入的樣式會被包裹在 <style> 標籤中並插入到 <head> 的最末端,因此在層疊順序中具有最高優先權。
截圖擷取(ScreenshotCapture)
ScreenshotCapture 將 HTML 渲染為圖片而非 PDF,支援 PNG 與 JPEG 格式:
php
use Yeeefang\TcpdfNext\Artisan\ScreenshotCapture;
// 全頁截圖
ScreenshotCapture::create()
->loadUrl('https://example.com')
->fullPage()
->format('png')
->save('/tmp/screenshot.png');
// 指定視窗大小與 JPEG 品質
ScreenshotCapture::create()
->loadHtml($html)
->viewport(width: 1280, height: 720)
->format('jpeg')
->quality(85)
->save('/tmp/preview.jpg');裁切特定區域
透過 clip() 只擷取頁面中的特定矩形區域:
php
ScreenshotCapture::create()
->loadUrl('https://example.com')
->clip(x: 0, y: 0, width: 800, height: 600)
->save('/tmp/cropped.png');Chrome 程序設定
自訂 Chrome 路徑
php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
$renderer = HtmlRenderer::create(
chromePath: '/usr/bin/google-chrome-stable',
);額外啟動參數
透過 chromeArgs() 傳遞額外的 Chrome 命令列參數:
php
$renderer = HtmlRenderer::create()
->chromeArgs([
'--no-sandbox',
'--disable-dev-shm-usage',
'--disable-gpu',
'--font-render-hinting=none',
]);程序重複使用
預設情況下,每次渲染都會啟動並關閉一個 Chrome 程序。如果需要批次渲染多份 PDF,可以重複使用同一個程序以提升效能:
php
$renderer = HtmlRenderer::create()->persistent();
foreach ($invoices as $invoice) {
$renderer->loadHtml($invoice->html)
->save("/tmp/invoice-{$invoice->id}.pdf");
}
$renderer->close(); // 手動關閉 Chrome 程序效能建議
| 策略 | 說明 |
|---|---|
| 重複使用程序 | 使用 persistent() 避免重複啟動 Chrome |
| 避免 waitForTimeout | 改用 waitForSelector() 以縮短等待時間 |
| 縮小 HTML | 移除不必要的空白與註解 |
| 本地資源 | 將字型與圖片放在本地,避免網路延遲 |
| 停用動畫 | 注入 * { animation: none !important; } |
錯誤處理
Artisan 定義了明確的例外類別,方便進行精確的錯誤處理:
php
use Yeeefang\TcpdfNext\Artisan\Exceptions\ChromeNotFoundException;
use Yeeefang\TcpdfNext\Artisan\Exceptions\RenderTimeoutException;
use Yeeefang\TcpdfNext\Artisan\Exceptions\CdpException;
try {
HtmlRenderer::create()
->loadHtml($html)
->save('/tmp/output.pdf');
} catch (ChromeNotFoundException $e) {
// Chrome 執行檔不存在或路徑錯誤
} catch (RenderTimeoutException $e) {
// 渲染超過逾時上限
} catch (CdpException $e) {
// CDP 通訊錯誤(如連線中斷、協定錯誤)
}| 例外 | 觸發時機 |
|---|---|
ChromeNotFoundException | 找不到 Chrome 執行檔 |
RenderTimeoutException | 渲染逾時 |
CdpException | CDP WebSocket 通訊失敗 |
FileNotFoundException | loadFile() 指定的檔案不存在 |
MergeException | PDF 合併過程中發生錯誤 |