spatie/laravel-pdf
Generate PDFs from Laravel Blade views with a simple fluent API. Choose drivers like Browsershot/Chromium, Gotenberg, Cloudflare Browser Run, WeasyPrint, DOMPDF, or chrome-php. Use modern CSS, set page formats, and stream or save PDFs.
Installation:
composer require spatie/laravel-pdf
php artisan vendor:publish --provider="Spatie\Pdf\PdfServiceProvider"
Publish the config file to adjust default settings (e.g., driver, paths).
First Use Case: Generate a PDF from a Blade view in a controller:
use Spatie\Pdf\Facades\Pdf;
public function generatePdf()
{
return Pdf::view('pdfs.invoice', ['data' => $data])
->format('a4')
->name('document.pdf');
}
Key Files to Review:
config/pdf.php: Driver configuration (e.g., browsershot, dompdf).resources/views/pdfs/: Store Blade templates for PDFs.app/Providers/AppServiceProvider.php: Register macros or custom logic if needed.Driver Selection:
Pdf::driver('dompdf') for lightweight, dependency-free PDFs.Pdf::driver('browsershot') for modern CSS (e.g., Flexbox/Grid) support.Pdf::driver('gotenberg') for Docker-based, scalable PDF generation.Pdf::driver('dompdf')->view('pdfs.report')->save('report.pdf');
Dynamic PDF Generation:
Pdf::view('pdfs.invoice', ['user' => $user, 'items' => $items])
->format('a4')
->save(storage_path("app/{$user->id}_invoice.pdf"));
Queued PDFs:
Pdf::view('pdfs.heavy-report', ['data' => $data])
->saveQueued('reports/heavy-report.pdf');
Email Attachments:
toMailAttachment():
$pdf = Pdf::view('pdfs.quote', ['quote' => $quote])
->name('quote.pdf')
->toMailAttachment();
Mail::send([...], function ($message) use ($pdf) {
$message->attach($pdf);
});
Macros for Reusability:
PdfBuilder with custom methods in AppServiceProvider:
Pdf::macro('withLogo', function () {
return $this->withOptions(['header-html' => view('pdfs.header')]);
});
// Usage:
Pdf::view('pdfs.document')->withLogo()->save('document.pdf');
CSS/Styling:
Browsershot/WeasyPrint for advanced CSS (e.g., @page rules for headers/footers).Testing:
Pdf::fake() to mock PDF generation in tests:
Pdf::fake();
$response = $this->get('/download-pdf');
Pdf::assertRespondedWithPdf();
Storage:
save(), saveQueued(), or generatePdfContent():
$pdfContent = Pdf::view('pdfs.document')->generatePdfContent();
Storage::disk('s3')->put('documents/report.pdf', $pdfContent);
Driver Compatibility:
puppeteer/poppler-utils are installed.GOTENBERG_URL in .env.Memory Limits:
saveQueued() or optimize Blade templates.Local File Access:
Pdf::driver('browsershot')->withBrowsershot(function ($browsershot) {
$browsershot->setOption('disable-web-security', true);
});
Queue Defaults:
PdfBuilder options. Explicitly set defaults in PdfServiceProvider:
Pdf::macro('setDefaults', function () {
Pdf::setOption('format', 'a4');
Pdf::setOption('margin-top', '20mm');
});
Testing Quirks:
Pdf::fake() only works with Pdf::view() or Pdf::loadView(). Avoid Pdf::load() in tests.contains() are case-sensitive and require the PDF to be saved first.config/pdf.php to log driver errors:
'debug' => env('PDF_DEBUG', false),
config/browsershot.php.docker ps).Custom Drivers:
Spatie\Pdf\Contracts\Driver to add support for new backends (e.g., headless Chrome via chrome-php/chrome).PDF Metadata:
setMetadata():
Pdf::view('pdfs.document')
->setMetadata([
'title' => 'My Document',
'author' => 'Laravel App',
])
->save('document.pdf');
Headers/Footers:
header-html/footer-html options with Browsershot/WeasyPrint:
Pdf::view('pdfs.report')
->withOptions([
'header-html' => view('pdfs.header', ['page' => '<page>']),
'footer-html' => view('pdfs.footer'),
])
->save('report.pdf');
Raw Content:
$pdfContent = Pdf::view('pdfs.document')->generatePdfContent();
// Use $pdfContent (e.g., send via API or store in DB)
Default Driver:
config/pdf.php under default_driver. Override per call with Pdf::driver('name').Browsershot Options:
withBrowsershot():
Pdf::driver('browsershot')
->withBrowsershot(function ($browsershot) {
$browsershot->setOption('timeout', 30000);
})
->view('pdfs.document')
->save('document.pdf');
WeasyPrint:
weasyprint installed. Configure in config/pdf.php:
'weasyprint' => [
'binary' => '/usr/local/bin/weasyprint',
],
How can I help you explore Laravel packages today?