Install Dependencies:
# Install Puppeteer (Ubuntu example)
curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs gconf-service libasound2 libatk1.0-0
sudo npm install --global --unsafe-perm puppeteer
Verify: Run puppeteer --version in terminal.
Add Bundle:
composer require eckinox/pdf-bundle
Configure Request Context (config/services.yaml):
parameters:
router.request_context.host: 'your-app.com'
router.request_context.scheme: 'https'
Create a Twig Template (resources/views/report.html.twig):
<html>
<body>
<h1>{{ title }}</h1>
<p>Generated on {{ date }}</p>
</body>
</html>
Generate PDF in Controller (app/Http/Controllers/ReportController.php):
use Eckinox\PdfBundle\Pdf\PdfGeneratorInterface;
public function generatePdf(PdfGeneratorInterface $pdfGenerator)
{
$pdf = $pdfGenerator->renderPdf('report', [
'title' => 'Monthly Report',
'date' => now()->format('Y-m-d')
]);
return $pdf->download('report.pdf');
}
Test:
Visit /report in your browser to trigger the download.
invoice.html.twig with placeholders for {client_name}, {amount}, {due_date}.$pdf = $pdfGenerator->renderPdf('invoice', [
'client_name' => $client->name,
'amount' => $invoice->total,
'due_date' => $invoice->due_date->format('Y-m-d')
]);
return $pdf->download("invoice_$invoice->id.pdf");
renderPdf() to populate Twig variables.base.pdf.twig) for consistent headers/footers.@page rules for margins:
@page {
size: A4;
margin: 1cm;
}
| Use Case | Method | Example |
|---|---|---|
| Browser Preview | output('filename.pdf') |
return $pdf->output('preview.pdf'); |
| Force Download | download('filename.pdf') |
return $pdf->download('invoice.pdf'); |
| Store in Filesystem | getContent() + file_put_contents |
$content = $pdf->getContent(); file_put_contents('storage/reports/report.pdf', $content); |
| Upload to S3 | getContent() + AWS SDK |
$s3->putObject(['Body' => $pdf->getContent()], 'reports/report.pdf'); |
namespace App\Services;
use Eckinox\PdfBundle\Pdf\PdfGeneratorInterface;
class PdfService {
public function __construct(private PdfGeneratorInterface $generator) {}
public function generateCertificate(string $name): string {
return $this->generator->renderPdf('certificate', ['name' => $name])->getContent();
}
}
config/services.php:
$app->bind(PdfService::class, function ($app) {
return new PdfService($app->make(PdfGeneratorInterface::class));
});
$pdf = $pdfGenerator->renderPdf('template', [], FormatFactory::a4());
$format = new Format("5in", "7in");
$pdf = $pdfGenerator->renderPdf('template', [], $format);
// Dispatch job
GeneratePdfJob::dispatch($userId, 'report_template');
// Job class
public function handle() {
$pdf = $this->generator->renderPdf('report_template', ['user' => User::find($this->userId)]);
Storage::put("reports/user_{$this->userId}.pdf", $pdf->getContent());
}
public function build() {
$pdf = app(PdfGeneratorInterface::class)->renderPdf('invoice', $this->data);
return $this->attachData($pdf->getContent(), 'invoice.pdf');
}
public function toMail($notifiable) {
$pdf = app(PdfGeneratorInterface::class)->renderPdf('receipt', ['order' => $this->order]);
return (new MailMessage)
->subject('Your Receipt')
->attachData($pdf->getContent(), 'receipt.pdf');
}
$excel = Excel::download(new UsersExport, 'users.xlsx');
$pdf = app(PdfGeneratorInterface::class)->renderPdf('excel_to_pdf', ['content' => $excel->getContent()]);
public function generatePdf() {
$pdf = app(PdfGeneratorInterface::class)->renderPdf('livewire_report', $this->data);
return response()->streamDownload(function () use ($pdf) {
echo $pdf->getContent();
}, 'report.pdf');
}
PdfGeneratorInterface in tests:
$mock = Mockery::mock(PdfGeneratorInterface::class);
$mock->shouldReceive('renderPdf')->andReturn(new class implements PdfInterface {
public function output(string $filename = null) { return new Response(); }
public function download(string $filename = null) { return new Response(); }
public function getContent() { return 'PDF_CONTENT'; }
});
Puppeteer Dependencies:
puppeteer to fail silently.Failed to launch the browser process! errors.Large PDF Filesizes:
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<image href="{{ asset('image.png') }}" width="100" height="100" />
</svg>
CSS Margins Ignored:
@page margins in CSS are not respected by Puppeteer.cm, in) and apply margins to the <body> or <div>:
body { margin: 1cm; }
Font Rendering Issues:
@font-face {
font-family: 'CustomFont';
src: url('/fonts/CustomFont.woff2') format('woff2');
}
body { font-family: 'CustomFont', sans-serif; }
Memory Limits:
memory_limit.memory_limit in php.ini or optimize templates (e.g., lazy-load images).Filename Sanitization:
Str::slug() or Str::of($filename)->slug() to sanitize:
$filename = Str::slug($user->name) . '.pdf';
return $pdf->download($filename);
Headless Chrome Crashes:
How can I help you explore Laravel packages today?