Tính năng nâng cao
Ngoài render HTML sang PDF cơ bản, package Artisan cung cấp tiện ích cho ghép document, chèn style toàn cục, chụp ảnh màn hình và tinh chỉnh hành vi Chrome.
Ghép PDF
Class PdfMerger kết hợp nhiều nguồn HTML thành một PDF document duy nhất. Mỗi nguồn được render dạng section riêng, và kết quả được nối theo thứ tự.
use Yeeefang\TcpdfNext\Artisan\PdfMerger;
use Yeeefang\TcpdfNext\Artisan\RenderOptions;
$merger = PdfMerger::create();
$merger
->addHtml('<h1>Cover Page</h1><p>Annual Report 2026</p>')
->addFile('/templates/chapter-1.html')
->addFile('/templates/chapter-2.html')
->addUrl('https://charts.example.com/annual-summary')
->addHtml('<h1>Appendix</h1><p>Supporting data tables.</p>');
$merger->save('/reports/annual-2026.pdf');Option theo section
Mỗi section có thể có RenderOptions riêng. Ví dụ, trang bìa ngang và chương dọc.
$coverOptions = RenderOptions::create()
->setPageSize('A4')
->setLandscape(true)
->setPrintBackground(true);
$chapterOptions = RenderOptions::create()
->setPageSize('A4')
->setLandscape(false)
->setDisplayHeaderFooter(true)
->setFooterTemplate('
<div style="font-size: 8px; text-align: center; width: 100%; color: #888;">
Page <span class="pageNumber"></span>
</div>
');
PdfMerger::create()
->addHtml('<h1>Cover</h1>', options: $coverOptions)
->addFile('/templates/chapter-1.html', options: $chapterOptions)
->addFile('/templates/chapter-2.html', options: $chapterOptions)
->save('/reports/merged.pdf');Chèn CSS
Class StyleInjector thêm CSS rule trước trang render. Hữu ích để áp dụng stylesheet thương hiệu toàn cục cho template bạn không kiểm soát.
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
use Yeeefang\TcpdfNext\Artisan\StyleInjector;
$injector = StyleInjector::create()
->addCss('
body {
font-family: "Inter", "Noto Sans TC", sans-serif;
font-size: 11pt;
line-height: 1.6;
color: #333;
}
h1 { color: #1a237e; }
')
->addCssFile('/styles/brand.css');
HtmlRenderer::create()
->loadFile('/templates/report.html')
->withStyleInjector($injector)
->save('/output/branded-report.pdf');Nhiều lớp Style
Style được chèn theo thứ tự thêm vào. Rule sau ghi đè rule trước, theo CSS specificity chuẩn.
$injector = StyleInjector::create()
->addCssFile('/styles/reset.css')
->addCssFile('/styles/brand.css')
->addCss('table { page-break-inside: avoid; }'); // ghi đèChụp ảnh màn hình
Class ScreenshotCapture render HTML sang định dạng hình ảnh thay vì PDF. Hữu ích cho tạo thumbnail, preview mạng xã hội hoặc visual regression testing.
use Yeeefang\TcpdfNext\Artisan\ScreenshotCapture;
// Chụp ảnh toàn trang dạng PNG
ScreenshotCapture::create()
->loadHtml('<h1>Preview</h1><p>This will be a PNG image.</p>')
->fullPage(true)
->format('png')
->save('/output/preview.png');JPEG với chất lượng
ScreenshotCapture::create()
->loadUrl('https://example.com/dashboard')
->format('jpeg')
->quality(85)
->save('/output/dashboard.jpg');Cấu hình Viewport
ScreenshotCapture::create()
->loadFile('/templates/email.html')
->viewport(width: 1200, height: 800)
->deviceScaleFactor(2) // retina
->fullPage(false)
->save('/output/email-preview.png');Cấu hình Chrome
Đường dẫn Binary tùy chỉnh
Artisan tự phát hiện Chrome trên đường dẫn OS phổ biến. Ghi đè với chromePath.
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
$renderer = HtmlRenderer::create(
chromePath: '/opt/google/chrome/chrome',
);Hoặc đặt biến môi trường CHROME_PATH toàn cục.
Flag Headless Mode
Artisan truyền --headless=new mặc định (Chrome 112+). Bạn có thể thêm flag cho môi trường cụ thể.
$renderer = HtmlRenderer::create(
chromeFlags: [
'--no-sandbox', // bắt buộc trong Docker
'--disable-gpu', // khuyên dùng trong Docker
'--disable-dev-shm-usage', // tránh vấn đề /dev/shm
'--font-render-hinting=none',
],
);Connection Pooling
Cho tình huống throughput cao, tái sử dụng một instance Chrome cho nhiều render. Điều này loại bỏ chi phí khởi động (khoảng 300--500 ms) cho mỗi render tiếp theo.
use Yeeefang\TcpdfNext\Artisan\ChromeBridge;
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
// Tạo bridge persistent
$bridge = ChromeBridge::create(chromePath: '/usr/bin/chromium');
// Tái sử dụng cho nhiều render
foreach ($reports as $report) {
HtmlRenderer::createWithBridge($bridge)
->loadHtml($report->html)
->save("/output/{$report->id}.pdf");
}
// Đóng rõ ràng khi hoàn tất
$bridge->close();Xử lý lỗi
Mọi exception Artisan extend Yeeefang\TcpdfNext\Artisan\Exceptions\ArtisanException.
use Yeeefang\TcpdfNext\Artisan\Exceptions\RenderException;
use Yeeefang\TcpdfNext\Artisan\Exceptions\ChromeNotFoundException;
use Yeeefang\TcpdfNext\Artisan\Exceptions\TimeoutException;
try {
HtmlRenderer::create()->loadUrl($url)->save($path);
} catch (ChromeNotFoundException $e) {
// Cài Chrome hoặc đặt CHROME_PATH
} catch (TimeoutException $e) {
// Tăng timeout hoặc kiểm tra mạng
} catch (RenderException $e) {
// Kiểm tra $e->getMessage() để biết chi tiết
}| Exception | Nguyên nhân phổ biến |
|---|---|
ChromeNotFoundException | Chrome chưa cài, CHROME_PATH sai |
TimeoutException | Trang chậm, JS promise chưa resolve, vấn đề mạng |
RenderException | HTML không hợp lệ, Chrome crash, lỗi ghi đĩa |
Mẹo hiệu suất
- Tái sử dụng instance Chrome -- Dùng
ChromeBridgecho thao tác batch. - Tối thiểu JavaScript -- JS càng ít Chrome phải thực thi, render càng nhanh.
- Inline CSS quan trọng -- Tránh tải stylesheet bên ngoài khi có thể.
- Đặt timeout chặt -- Fail nhanh trên trang lỗi thay vì chặn queue.
- Dùng
setPrintBackground(false)-- Bỏ qua render nền khi không cần.
Bước tiếp theo
- Render Option -- Kích thước trang, margin và template header/footer.
- Thiết lập Docker -- Chạy Artisan trong môi trường container.
- Tổng quan -- Tóm tắt package và cài đặt.