pxlrbt/laravel-pdfable
pxlrbt/laravel-pdfable adds a lightweight trait to Eloquent models for generating PDFs. Point a model at a Blade view, then download or stream the finished PDF with a single method call—keeping document generation out of your controllers. Handy for invoices, reports, and exports.
Architecture fit. laravel-pdfable is a thin adapter between Laravel's Blade layer and a PDF engine, not a document platform. Its architectural value is the driver seam: one fluent API (Pdf::view(...)->driver(...)->paper(...)->render()) over Dompdf (pure PHP) and Browsershot (Node/Chromium). That seam lets a TPM defer the fidelity-vs-cost decision until volume data exists, which is the single most useful thing this package contributes to a roadmap. It fits applications where documents are model-bound artifacts — invoices, receipts, statements, packing slips, certificates — and does not fit as a general reporting engine: charts, PDF/A tagging, digital signatures, interactive forms, and precise repeating headers are all out of scope. Treat it as an implementation detail behind your own DocumentRenderer interface, not as infrastructure you build on directly.
Integration feasibility. Low effort, bounded blast radius. One Composer require, one config publish, a model trait plus a builder, and a small driver class set. A competent Laravel developer can render a real file in a day. The real cost is not integration — it's the decisions integration forces (sync vs. queued, artifact storage, template ownership, driver per document type), which are product decisions a TPM should make before the first ticket rather than discover during the third.
Technical risk. Ranked by likelihood × cost:
composer show laravel/framework before promising a date.no-sandbox, timeouts, memory ceilings. Debugging Chromium-through-PHP-inside-a-queue-worker is a bad first experience — validate Chromium standalone before wiring it into a job.Pdf::fake() records intent and passes while the real PDF is empty. Neither surfaces in CI.{!! !!} in a PDF template is still an XSS/HTML-injection vector into a file you may email or archive.Key questions to answer before committing.
Stack fit. Requires Laravel 11+, PHP compatible with that line, Composer, and Blade — all of which a Laravel shop already has. Browsershot adds Node, a Chromium binary, and a container image that carries both; Dompdf adds nothing. It integrates naturally with Eloquent (model-bound rendering), the filesystem abstraction (artifact storage), queues (async generation), and the test suite (Pdf::fake()). No new runtime, no new service, no new vendor relationship on the Dompdf path — which is why it is a defensible first move even for a conservative team.
Migration path. Two shapes, both incremental:
DocumentRenderer first, wrap the existing implementations behind it, ship that refactor with no behaviour change, then replace implementations one document type at a time. This preserves the option to stop halfway.resources/views/pdf/ namespace on day one. Retrofitting the async/storage pattern later means rewriting every call site; establishing it first costs almost nothing.Do not do a big-bang consolidation of all document types. The package's economics are that document #1 is a spike, #2–#5 are near-marginal, and #6 is where you formalize (shared layout, template resolution, storage/expiry). Plan the sequence, not the ticket.
Compatibility watch-list.
.env is read at cache time.APP_URL must be correct in every environment; workers build asset URLs from it, and a wrong value is a missing logo nobody notices for a quarter.Sequencing.
DocumentRenderer and the thin adapter.Pdf::fake() for wiring (view, data, driver, filename), plus one slow real-render test in a separate group. Assert authorization (can user A fetch user B's invoice?) and artifact cleanup.Maintenance. Low code churn, low upstream leverage. The release history is dominated by Dependabot bumps plus framework-support PRs — a healthy signal that the maintainer keeps CI green, but not a signal of active feature development. Budget for the possibility that your team becomes the de facto maintainer of its own fork, and make sure that fork is a one-file change rather than a rewrite. The v1.0.0 Pest suite is a genuine asset here: it is the real contract for method signatures and fake behaviour, and it means the package is testable in a way many single-maintainer packages are not.
Support. No vendor, no SLA, no support channel beyond GitHub issues. The internal support burden concentrates almost entirely in two places: fonts/images that silently fail, and "the PDF looks wrong" reports that need triage across driver, template, environment, and asset availability. Write that runbook early — it is a five-line decision tree that saves hours per ticket. The fake-versus-reality gap is the cultural risk: a green suite will happily coexist with a blank page, so someone must open real documents after every driver or template change.
Scaling. The cost curve is driver-dependent and volume-dependent, and that is the whole point of the seam. Dompdf is cheap per document but degrades hard — thousands of rows or embedded high-res images will hit memory_limit or time out, and reaching for ini_set('memory_limit', ...) is a signal to move that document type rather than tune the box. Browsershot is accurate but CPU- and memory-hungry: dedicated queue, bounded workers, low Puppeteer concurrency, explicit tries, job timeout slightly above the render timeout, and periodic worker recycling because long-running workers leak. Cache aggressively on input hash plus template version — identical inputs should produce a reused artifact. Watch for N+1s in Blade: a queued render taking forty seconds is usually lazy loading, not the renderer.
Failure modes to design against.
| Failure | Symptom | Mitigation |
|---|---|---|
| Silent asset/webfont failure | Blank logo, no exception | Local absolute paths, fonts registered in config, present on worker image |
| Fake passes, real render breaks | Green CI, empty PDF | One or two slow real-render tests; open documents after upgrades |
| OOM / timeout on large documents | Failed jobs, partial files | SQL pre-aggregation, chunked reports, downscaled images, or driver move |
| Retry duplicates | Same invoice emailed twice | Idempotent notification keyed on artifact |
| Config cache masking driver swap | Change has no effect in staging | Cache rebuild in deploy pipeline |
| Public artifact exposure | Invoice URL guessable | Private disk, signed short-lived route, tested cleanup |
| Injected HTML in templates | Untrusted content rendered raw | Escape by default; {!! !!} reviewed deliberately |
Ramp-up. The API surface is small enough that a mid-level Laravel developer is productive in a day, and the model-bound pattern ($invoice->pdf()->download()) is intuitive enough to explain in a standup. The scarce skills are elsewhere: CSS for print (pagination, break-inside, repeating thead, @page) and Chromium operations. Those are the two competencies to deliberately seed on the team, because they determine whether the sixth document type is a sprint or a program. Name one owner for the PDF template system — shared layout, print CSS conventions, and template resolution — before the second document type ships, not after the fifth.
How can I help you explore Laravel packages today?