Bình thường khi làm việc với Laravel và nghiệp vụ phải xuất file ra PDF, luôn là những điều thật sự khó khăn với các lập trình viên Backend. Bản chất trên PHP đã chứa một extension hỗ trợ việc gen HTML ra PDF rồi.
Bạn có thể tham khảo:
Hay một thư viện khác với nhiều nâng cấp đáng giá hơn được viết bằng C++ hỗ trợ việc gen HTML ra PDF như là:
- https://github.com/KnpLabs/snappy
- Sử dụng thư viện https://wkhtmltopdf.org/
Hầu hết các công cụ và thư viện trên hỗ trợ rất hạn chế các thuộc tính của CSS3 và HTML5 vì vậy có cực kỳ nhiều khó khăn để chúng ta hoàn thành một task nào đó.
Giải pháp
Một công ty sản xuất các thư viện hỗ trợ của Bỉ ra mắt thư viện này khá hay. Bản chất của nó chính là dùng trực tiếp Chrome hay Chromium Kernel trên OS gốc (OS server) của chúng ta để chụp ảnh và chuyển vào file PDF.
Bản thân ngôn ngữ lập trình PHP không thể làm được điều đó, và nó được thực hiện qua Javascript (NodeJS) và chính xác hơn là thư viện:
Thứ mà pupperteer làm là nhét toàn bộ cục chrome đó lại và bắt nó thực hiện các hành động mà chúng ta chỉ định.
=> Điều này khá là nặng, chậm ảnh hưởng đến performance của hệ thống, nhưng đánh đổi lại là chúng ta có thể gen ra một file PDF một cách đơn giản và dễ dàng. Có thể sử dụng cả Javascript tác động đến DOM trước khi build ra file, cùng với đó là hỗ trợ tất cả những gì hỗ trợ trên Chrome như HTML5, CSS3....
Cài đặt
composer require spatie/laravel-pdfCài đặt laravel-pdf, bên trong đó đồng thời cũng cài đặt một thư viện khác đó là:
Lúc này ta cần cài đặt thêm NodeJS và NPM để cài đặt và chạy lệnh cho Pupperteer
Sau đó ta cài đặt pupperteer lên dự án đang chạy hoặc ta có thể cài global cho các dự án khác nữa.
npm install puppeteerhoặc cài global
npm install puppeteer --location=globalTạo file config cho Pupperteer tại thư mục gốc của dự án:
.puppeteerrc.cjs
const {join} = require('path');
/**
* @type {import("puppeteer").Configuration}
*/
module.exports = {
// Changes the cache location for Puppeteer.
cacheDirectory: join(__dirname, '.cache', 'puppeteer'),
};
Nếu sử dụng Linux mà khi chạy thấy báo thông báo lỗi liên quan đến Chrome chưa được chạy hay khởi động có thể tham khảo cài đặt thêm các libs:
Chú ý: Khi chạy trên Docker (laradock), cài đặt các lib trên liên quan đến Node, NPM, Chrome ... mà thấy báo thiếu hoặc lỗi thì chú ý kiểm tra xem PHP đang chạy ở đâu ?
Mình hay gặp lỗi khi kiểm tra rõ ràng Node, NPM ... được cài đặt tại Workspace rồi nhưng mà vẫn lỗi, Sau mới phát hiện ra cần cài đặt tren PHP-fpm mới đúng.
Sử dụng:
use Spatie\Browsershot\Browsershot;
use Spatie\LaravelPdf\Facades\Pdf;
return Pdf::view('*.blade.php', $data)
->...
->withBrowsershot(fn (Browsershot $browsershot) => $browsershot->noSandbox())
->...Chúc các bạn thành công.