HTML Renderer
Class HtmlRenderer là điểm truy cập chính cho mọi thao tác HTML sang PDF. Nó cung cấp fluent API để tải nội dung, cấu hình output và render PDF document.
Factory Method
Tạo instance renderer với factory static create().
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
// Cấu hình mặc định (tự phát hiện Chrome)
$renderer = HtmlRenderer::create();
// Với đường dẫn Chrome binary tùy chỉnh
$renderer = HtmlRenderer::create(
chromePath: '/usr/bin/google-chrome',
);
// Với thư mục tạm tùy chỉnh
$renderer = HtmlRenderer::create(
chromePath: '/usr/bin/chromium',
tempDir: '/tmp/artisan-render',
);Tải nội dung
Từ chuỗi
Truyền HTML thô trực tiếp với loadHtml(). Chuỗi có thể là document HTML đầy đủ hoặc fragment.
$renderer->loadHtml('<h1>Hello, World!</h1>');Khi bạn truyền fragment, Artisan tự động bọc nó trong document <!DOCTYPE html> tối thiểu.
Từ file cục bộ
Tải file .html từ ổ đĩa với loadFile(). Đường dẫn tương đối đến stylesheet, hình ảnh và script trong file được phân giải từ thư mục của file.
$renderer->loadFile('/templates/quarterly-report.html');Từ URL
Tải và render URL trực tiếp với loadUrl(). Trang được tải trong Chrome headless, nên JavaScript thực thi và AJAX call hoàn tất trước khi render.
$renderer->loadUrl('https://reports.example.com/q4-2026');Bạn có thể đặt timeout navigation để tránh treo trên trang chậm:
$renderer->loadUrl('https://example.com/dashboard', timeoutMs: 30000);Method xuất
Lưu ra file
$renderer->save('/output/report.pdf');Lấy dạng chuỗi
Lấy byte PDF thô để xử lý tiếp (vd: lưu database, đính kèm email).
$pdfContent = $renderer->toString();
// Ví dụ: lưu database
DB::table('documents')->insert([
'name' => 'report.pdf',
'content' => $pdfContent,
]);Gửi đến trình duyệt
Stream PDF trực tiếp đến HTTP response với header phù hợp.
// Hiển thị inline (trình xem PDF trình duyệt)
$renderer->output('report.pdf', 'inline');
// Bắt buộc tải xuống
$renderer->output('report.pdf', 'download');Ví dụ đầy đủ: Hóa đơn
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
$html = <<<'HTML'
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: 'Inter', sans-serif; margin: 20mm; }
.header { display: flex; justify-content: space-between; align-items: flex-start; }
.company { font-size: 24px; font-weight: 700; color: #1a237e; }
.meta { text-align: right; color: #666; font-size: 13px; }
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin: 30px 0; }
.grid section { padding: 15px; background: #f8f9fa; border-radius: 6px; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th { background: #1a237e; color: white; padding: 10px 12px; text-align: left; }
td { border-bottom: 1px solid #e0e0e0; padding: 10px 12px; }
tr:nth-child(even) { background: #fafafa; }
.total { font-weight: 700; font-size: 18px; text-align: right; margin-top: 20px; }
</style>
</head>
<body>
<div class="header">
<div class="company">Acme Corporation</div>
<div class="meta">
Invoice #2026-001<br>
Date: 2026-02-16<br>
Due: 2026-03-16
</div>
</div>
<div class="grid">
<section>
<strong>Bill To</strong><br>
Jane Smith<br>
456 Oak Avenue<br>
Springfield, IL 62704
</section>
<section>
<strong>Ship To</strong><br>
Jane Smith<br>
789 Elm Street<br>
Springfield, IL 62704
</section>
</div>
<table>
<thead>
<tr>
<th>Item</th>
<th>Qty</th>
<th>Unit Price</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr><td>Web Development</td><td>40 hrs</td><td>$150.00</td><td>$6,000.00</td></tr>
<tr><td>UI/UX Design</td><td>20 hrs</td><td>$125.00</td><td>$2,500.00</td></tr>
<tr><td>Annual Hosting</td><td>1</td><td>$1,200.00</td><td>$1,200.00</td></tr>
</tbody>
</table>
<div class="total">Total: $9,700.00</div>
</body>
</html>
HTML;
HtmlRenderer::create()
->loadHtml($html)
->save('/invoices/2026-001.pdf');Method Chaining
Mọi setter trên HtmlRenderer trả về $this, cho phép fluent builder pattern.
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
use Yeeefang\TcpdfNext\Artisan\RenderOptions;
use Yeeefang\TcpdfNext\Artisan\StyleInjector;
HtmlRenderer::create()
->loadFile('/templates/report.html')
->withOptions(
RenderOptions::create()
->setPageSize('A4')
->setLandscape(false)
->setMargins(top: 15, right: 10, bottom: 15, left: 10)
->setPrintBackground(true)
)
->withStyleInjector(
StyleInjector::create()
->addCss('body { font-size: 12pt; }')
)
->save('/output/styled-report.pdf');Xử lý lỗi
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
use Yeeefang\TcpdfNext\Artisan\Exceptions\RenderException;
use Yeeefang\TcpdfNext\Artisan\Exceptions\ChromeNotFoundException;
use Yeeefang\TcpdfNext\Artisan\Exceptions\TimeoutException;
try {
HtmlRenderer::create()
->loadUrl('https://example.com/slow-report')
->save('/output/report.pdf');
} catch (ChromeNotFoundException $e) {
// Không tìm thấy binary Chrome — kiểm tra CHROME_PATH
logger()->error('Chrome not installed: ' . $e->getMessage());
} catch (TimeoutException $e) {
// Trang mất quá lâu để tải hoặc render
logger()->warning('Render timed out: ' . $e->getMessage());
} catch (RenderException $e) {
// Bất kỳ lỗi render khác
logger()->error('Render failed: ' . $e->getMessage());
}Bước tiếp theo
- Render Option -- Tinh chỉnh kích thước trang, margin, header và footer.
- Tính năng nâng cao -- Ghép PDF, chèn CSS, chụp ảnh màn hình.