spatie/laravel-pdf
Generate PDFs in Laravel from Blade views with a fluent API. Choose drivers like Chromium (Browsershot), Gotenberg, Cloudflare, WeasyPrint, or DOMPDF. Save to disk or return as a response, with support for modern CSS and paged media.
Installation:
composer require spatie/laravel-pdf
Run migrations if using the pdf table:
php artisan migrate
First PDF Generation:
Use the Pdf facade to generate a PDF from a Blade view:
use Spatie\Pdf\Pdf;
$pdf = Pdf::loadView('invoice', ['data' => $invoiceData])
->setOptions(['defaultFont' => 'DejaVu Sans'])
->save(storage_path('app/invoice.pdf'));
Quick Use Case: Generate an invoice PDF on demand:
public function generateInvoice($invoiceId)
{
$invoice = Invoice::findOrFail($invoiceId);
return Pdf::loadView('invoices.pdf', compact('invoice'))
->stream('invoice-' . $invoice->id . '.pdf');
}
config/pdf.php (default options, paths, and storage settings).Spatie\Pdf\Facades\Pdf (primary API entry point).Spatie\Pdf\PdfServiceProvider (bootstrapping logic).Blade-to-PDF Conversion:
// Generate and download
return Pdf::loadView('report', ['items' => $items])
->download('report.pdf');
// Generate and stream (for direct browser display)
return Pdf::loadView('report', ['items' => $items])
->stream('report.pdf');
Dynamic PDF Options: Override default settings per request:
Pdf::loadView('document')
->setOptions([
'format' => 'A4',
'orientation' => 'landscape',
'margin_top' => 20,
'margin_bottom' => 20,
]);
Storing PDFs: Save to disk or database:
// Disk storage
$path = Pdf::loadView('document')->save(storage_path('pdfs/document.pdf'));
// Database storage (if using `pdf` table)
$pdf = Pdf::loadView('document')->save();
$pdf->path; // Retrieve path later
Queueing PDF Generation: Use Laravel queues to offload heavy PDF generation:
// Job
public function handle()
{
Pdf::loadView('large-report', ['data' => $this->data])
->save(storage_path('reports/large-report.pdf'));
}
// Dispatch
GenerateLargeReportJob::dispatch($data);
Reusing PDF Logic: Create a service class for complex PDFs:
class InvoicePdfService
{
public function generate(Invoice $invoice)
{
return Pdf::loadView('invoices.detailed', compact('invoice'))
->setOptions(['defaultFont' => 'Arial']);
}
}
Laravel Mail: Attach PDFs to emails:
Mail::send([], [], function ($message) use ($pdf) {
$message->subject('Your Invoice');
$message->attach(
$pdf->save(storage_path('temp/invoice.pdf')),
['as' => 'invoice.pdf', 'mime' => 'application/pdf']
);
});
Laravel Notifications: Send PDFs via notifications:
public function toMail($notifiable)
{
$pdf = Pdf::loadView('receipt', ['order' => $this->order]);
return (new MailMessage)
->subject('Your Receipt')
->attach($pdf->save(storage_path('temp/receipt.pdf')));
}
API Responses: Return PDFs in API responses:
return response()->streamDownload(
function () use ($pdf) {
echo $pdf->save(storage_path('temp/api-pdf.pdf'));
},
'api-report.pdf'
);
Font Issues:
->setOptions(['defaultFont' => 'DejaVu Sans', 'fontSize' => 12]);
storage/logs/laravel.log for font-related errors.Memory Limits:
memory_limit in php.ini.->setOptions(['dpi' => 96]) to reduce resolution.Path Handling:
$path = storage_path('app/pdfs/' . $filename);
file_exists() before saving.Caching:
$filename = 'report-' . now()->timestamp . '.pdf';
DOM Complexity:
@media queries, position: fixed).->setOptions(['disableSmartShrinking' => true]).Log PDF Options:
$pdf = Pdf::loadView('view');
\Log::info('PDF Options:', $pdf->getOptions());
Inspect Generated HTML:
$html = Pdf::loadView('view')->getHtml();
file_put_contents(storage_path('debug.html'), $html);
Check DomPDF Errors: Enable DomPDF’s error handling:
->setOptions(['isHtml5ParserEnabled' => true, 'isRemoteEnabled' => true]);
Custom DomPDF Configuration:
Override DomPDF’s default settings globally in config/pdf.php:
'dompdf' => [
'font_cache' => storage_path('fonts'),
'tempDir' => storage_path('temp'),
'chroot' => null,
],
Event Listeners:
Listen for PDF generation events (e.g., PdfGenerated):
Pdf::loadView('document')->save(storage_path('pdfs/doc.pdf'))
->then(function ($path) {
// Post-processing (e.g., upload to S3)
});
Middleware: Restrict PDF generation to specific routes:
Route::middleware(['auth', 'can:generate-pdfs'])->group(function () {
// Routes requiring PDF generation
});
Testing: Mock PDF generation in tests:
Pdf::shouldReceive('loadView')
->once()
->andReturnSelf()
->shouldReceive('save')
->once()
->andReturn('/fake/path.pdf');
Dynamic Content: Use Blade components for reusable PDF sections:
// In Blade
@component('pdf.table', ['data' => $data])
// In PHP
Pdf::loadView('document', ['sections' => $sections]);
Localization: Support multiple languages by passing locale to the view:
Pdf::loadView('document', ['locale' => app()->getLocale()]);
Performance: Pre-generate static PDFs and serve them via CDN:
// Cache the PDF for 1 hour
$pdf = Pdf::loadView('static-page')->save(storage_path('cached/page.pdf'));
Security: Sanitize dynamic content to prevent DOMPDF injection:
$cleanedData = strip_tags($userInput, '<b><i><u>');
How can I help you explore Laravel packages today?