barryvdh/laravel-snappy
Generate PDF and image files in Laravel using wkhtmltopdf/wkhtmltoimage. Provides simple facades and service provider setup, config options, and easy rendering from views or HTML strings with headers, footers, and custom binaries.
Install the Package:
composer require barryvdh/laravel-snappy
Publish the config file:
php artisan vendor:publish --provider="Barryvdh\Snappy\ServiceProvider"
Configure Binaries:
Edit config/snappy.php to set paths to wkhtmltopdf and wkhtmltoimage binaries. For Docker, ensure these are installed in your container:
RUN apt-get update && apt-get install -y wkhtmltopdf
First Use Case: Generate a PDF from a Blade view in a controller:
use Barryvdh\Snappy\Facades\SnappyPdf;
public function generatePdf()
{
return SnappyPdf::loadView('pdf.template', ['data' => $data])
->setOption('margin-top', '20mm')
->setOption('margin-bottom', '20mm')
->stream('document.pdf');
}
Verify Installation:
Test with a simple Blade template (resources/views/pdf.template):
<h1>Hello, {{ $data['name'] }}!</h1>
<p>This is a test PDF.</p>
Visit the route to confirm PDF generation.
Pattern: Use Blade templates for dynamic PDFs.
// Controller
public function invoice($id)
{
$invoice = Invoice::find($id);
return SnappyPdf::loadView('invoices.pdf', compact('invoice'))
->setPaper('a4')
->stream("invoice-{$invoice->id}.pdf");
}
Template (resources/views/invoices.pdf):
<!DOCTYPE html>
<html>
<head>
<style>
table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid #ddd; padding: 8px; }
</style>
</head>
<body>
<h1>Invoice #{{ $invoice->number }}</h1>
<table>
<tr><th>Item</th><th>Qty</th><th>Price</th></tr>
@foreach($invoice->items as $item)
<tr>
<td>{{ $item->description }}</td>
<td>{{ $item->quantity }}</td>
<td>${{ number_format($item->price, 2) }}</td>
</tr>
@endforeach
</table>
</body>
</html>
Pattern: Dynamically generate PDFs from raw HTML (e.g., email templates).
$html = '<h1>Dynamic PDF</h1><p>Generated at: ' . now() . '</p>';
return SnappyPdf::loadHtml($html)
->setOption('encoding', 'UTF-8')
->download('dynamic.pdf');
Pattern: Offload PDF generation to background jobs for performance.
// Dispatch job
SnappyPdfJob::dispatch('invoices.pdf', ['invoice' => $invoice], 'invoice.pdf');
// Job class
use Barryvdh\Snappy\Facades\SnappyPdf;
use Illuminate\Bus\Queueable;
class SnappyPdfJob implements ShouldQueue
{
use Queueable;
public function handle()
{
$pdf = SnappyPdf::loadView($this->view, $this->data)
->setOptions($this->options);
Storage::put($this->filename, $pdf->output());
}
}
Pattern: Add consistent headers/footers to all PDFs.
// Config in snappy.php
'pdf' => [
'header-html' => resource_path('views/pdf/header.blade.php'),
'footer-html' => resource_path('views/pdf/footer.blade.php'),
'header-font-name' => 'DejaVuSans',
'footer-font-name' => 'DejaVuSans',
],
Header Template (resources/views/pdf/header.blade.php):
<div style="text-align: center; font-size: 12px;">
Company Name | Page <span class="page-number"></span>
</div>
Pattern: Convert HTML to images (e.g., thumbnails for previews).
use Barryvdh\Snappy\Facades\SnappyImage;
$image = SnappyImage::loadHtml('<h1>Preview</h1><p>This will be an image.</p>')
->setOption('width', 800)
->setOption('height', 600)
->get();
Storage::put('preview.png', $image);
use Barryvdh\Snappy\Facades\SnappyPdf;
public function __construct(private SnappyPdf $pdf) {}
Set options dynamically per request:
$pdf = SnappyPdf::loadView('template', $data)
->setOption('margin-top', '10mm')
->setOption('margin-bottom', '10mm')
->setOption('encoding', 'UTF-8');
Extend functionality using events:
// Listen for PDF generation events
SnappyPdf::listen('generating', function ($job) {
// Add custom logic before generation
$job->setOption('custom-key', 'custom-value');
});
SnappyPdf::listen('generated', function ($pdf) {
// Post-process the PDF
$pdf->setContent($pdf->getContent() . 'Custom footer');
});
Use SnappyPdf in tests with mocks or temporary files:
public function testPdfGeneration()
{
$pdf = SnappyPdf::loadHtml('<h1>Test</h1>');
$content = $pdf->get();
$this->assertStringContainsString('Test', $content);
}
wkhtmltopdf is not in the configured path.config/snappy.php and ensure binaries are installed:
which wkhtmltopdf # Linux/Mac
where wkhtmltopdf # Windows
FROM barryvdh/laravel-snappy:latest
COPY --from=builder /usr/local/bin/wkhtmltopdf /usr/local/bin/
position: fixed, flexbox) may not render as expected.table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; }
memory_limit in php.ini or .env:
memory_limit = 512M
SnappyPdf::loadHtml($html)->setOption('enable-javascript', true) cautiously.Arial, Times New Roman).snappy.php:
'pdf' => [
'font-path' => resource_path('fonts'),
],
queue_worker_max_jobs in .env:
QUEUE_W
How can I help you explore Laravel packages today?