setasign/fpdi
Import pages from existing PDFs and reuse them as templates in FPDF, TCPDF, or tFPDF. FPDI 2 is a modern, namespaced, PSR-4 compatible rewrite with major performance and memory improvements, no special PHP extensions required.
barryvdh/laravel-dompdf for hybrid workflows.tecnickcom/tcpdf.PdfTemplateGenerator) or used in commands/jobs (e.g., GenerateInvoiceJob).composer.json).| Risk Area | Mitigation Strategy |
|---|---|
| PDF Corruption | FPDI handles malformed PDFs gracefully (e.g., recursive structures, invalid cross-references). Use try-catch blocks for importPage()/useTemplate(). |
| Memory Leaks | FPDI 2.x optimizes memory (100% improvement over v1). Monitor with memory_get_usage() in long-running jobs. |
| PHP Version Support | Dropped PHP 7.1/5.6 (use PHP 8.0+). Laravel 9+ requires PHP 8.1+, so no conflict. |
| Performance | For large PDFs (>100MB), stream processing (e.g., setSourceFile() with streams) reduces memory spikes. |
| TCPDF/FPDF Conflicts | Use separate services (e.g., FpdfTemplateGenerator, TcpdfTemplateGenerator) to avoid class collisions. |
setasign/fpdi2 (successor) or TCPDF’s digital signatures.| Laravel Component | FPDI Integration Point |
|---|---|
| Service Providers | Register FPDI as a bindable service (e.g., app.bind('pdf.template', Fpdi::class)). |
| Commands | Use Artisan::command() to trigger PDF generation (e.g., php artisan pdf:invoice). |
| Jobs/Queues | Extend ShouldQueue for async generation (e.g., GeneratePdfJob). |
| Controllers | Inject PdfTemplateGenerator into controllers for on-demand PDFs (e.g., downloads). |
| Middleware | Validate PDF templates before processing (e.g., check file size, permissions). |
| Storage | Store templates in S3 or local disk (use Storage::disk()->path()). |
| Testing | Mock setSourceFile() in PHPUnit to avoid I/O during tests. |
DomPDF, manual HTML-to-PDF).// app/Services/PdfTemplateGenerator.php
class PdfTemplateGenerator {
public function generateInvoice(Invoice $invoice, string $templatePath) {
$pdf = new \setasign\Fpdi\Fpdi();
$pdf->AddPage();
$tplId = $pdf->importPage(1); // Template is page 1
$pdf->useTemplate($tplId, 10, 10, 180); // Position template
$this->addDynamicData($pdf, $invoice); // Inject data
return $pdf->Output('invoice.pdf', 'S');
}
}
try {
return $this->fpdiGenerator->generate($data);
} catch (Exception $e) {
return $this->dompdfGenerator->generate($data);
}
| Dependency | Compatibility Notes |
|---|---|
| Laravel 9/10 | No conflicts; FPDI is framework-agnostic. |
| PHP 8.0+ | Required (FPDI dropped PHP 7.1 support). |
| FPDF/TCPDF | Must match versions (e.g., FPDF 1.8.x for FPDI 2.6.x). Use composer.json constraints. |
| Storage Drivers | Works with local, S3, FTP (any stream-compatible source). |
| Queue Workers | Supports sync/async generation (test memory usage for large PDFs). |
/MediaBox slashes).PdfTemplateGenerator) with abstract methods for template loading/data injection.InvoicePdfGenerator, ContractPdfGenerator).useTemplate() + FPDF’s text/image methods to overlay data:
$pdf->SetFont('Arial', 'B', 12);
$pdf->SetXY(50, 50);
$pdf->Cell(0, 10, $invoice->amount);
'S'), file ('D'), or stream (for APIs).return response($pdf->Output('invoice.pdf', 'S'), 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="invoice.pdf"',
]);
PdfParserException) to a monitoring tool (Sentry, Laravel Horizon).| Task | Effort Level | Notes |
|---|---|---|
| Template Updates | Low | Edit source PDFs; no code changes needed. |
| Dependency Updates | Medium | Monitor FPDF/TCPDF/FPDI for breaking changes ( |
How can I help you explore Laravel packages today?