evosys21/pdflib
A PHP library for FPDF, TCPDF, and tFPDF that adds advanced multicell and table support. Build tag-formatted text with custom fonts, colors, links, alignment, and padding, plus feature-rich tables for PDF reports.
Architecture fit
evosys21/pdflib is not a PDF engine — it's an add-on layer of classes that sit on top of FPDF, TCPDF, or tFPDF and add two capabilities those engines lack: Advanced Multicell (tag-based rich text — font, size, style, color, links, sub/superscript, padding, tabs, per-tag alignment) and Advanced Table (rowspan/colspan, vertical + horizontal alignment, automatic page-break splitting, repeated headers, per-cell overrides, images, transparency). Architecturally it is a thin, framework-agnostic PHP library with no service container, no facade, and no Laravel coupling.
That is the right shape for the problem it solves, and the wrong shape for anything else. It fits cleanly if your stack already generates PDFs with FPDF/TCPDF/tFPDF and the recurring pain is exactly "rich text in a cell" and "tables that span pages." It is a poor fit if you have standardized on HTML→PDF (Dompdf, Snappy/wkhtmltopdf, Chromium) — porting to a primitive-drawing API is a rewrite, not an integration.
Integration feasibility
Moderate, with one specific blocker to price in. Per the FAQ, the package ships its own Pdf subclasses (src/Fpdf/Pdf.php, src/Tcpdf/Pdf.php, src/Tfpdf/Pdf.php) because FPDF exposes no getters/setters for widths, margins, or fonts. You must instantiate their class, not new FPDF(). Any existing in-house subclass that draws branded headers, footers, watermarks, or registers custom fonts has to be re-parented under theirs or refactored into composition. That is the single largest effort item and the first thing to scope.
Everything else is cheap: composer require, no published service provider to register, no config file, no migrations. A ~50-line adapter service in app/ gives you DI, config, and a testable seam.
Technical risk
Code risk is low; vendor risk is high.
evosys21/phplib while the repository and package name are pdflib. Verify the actual resolvable Composer name and tag before anyone writes code against it.Key questions to answer before approval
Pdf subclasses we inherit from.composer require resolve today, in a clean scratch project, at a pinned version?Stack fit
Native PHP/Composer, so it drops into a Laravel app without ceremony. It is deliberately not Laravel-native — no config publishing, no facade, no queue-aware API. Treat that as a feature: wrap it in one PdfRenderer / PdfDocumentFactory service, keep the library at arm's length, and the rest of the app never imports its namespaces directly.
Migration path
Incremental, document-by-document, never big-bang:
composer require, render one existing table-heavy document (invoice or statement) with Advanced Table. Compare output and render time against the current path. This validates questions 1–3 above and retires most of the uncertainty.EvoSys21\PdfLib\{Engine}\Pdf, carrying existing header/footer/branding logic. Register it as a singleton in the container. Existing documents keep using the legacy path behind a config flag.MultiCell line-wrapping loops, bold/underline styling hacks.Compatibility
Pin to a specific minor (^1.2) and pin the base engine explicitly in composer.json. Semver history is clean (0.9 → 1.0 → 1.1 → 1.2, no breaking churn in the 1.x line), and PHP 8.4 deprecations were addressed in 1.1.1 — verify against your actual PHP version rather than assuming. The underline feature added in 1.2.0 is the current head; treat anything below it as legacy.
Sequencing
Spike → adapter → one document → measure → fan out. Gate the fan-out on the Phase 0 output diff being visually acceptable and the package name/version resolving reliably. Do not let the migration run in parallel with an engine change (e.g., FPDF → TCPDF); those are two independent risk events and must not be compounded.
Maintenance
Small, low-churn surface: a handful of classes, no runtime services, no database, no background daemons. Upgrades are a Composer bump plus a regression run. Because the output is a binary, invest early in golden-file tests — snapshot the generated PDFs, assert on extracted text and a rendered-image diff. Without that, an upgrade regression is invisible until a customer sees a broken invoice.
Support
Community-only via GitHub issues and discussions. No SLA, no paid tier, no security response commitment. Mitigate with the MIT license: budget roughly 1–2 engineer-days per quarter as "insurance" — periodic dependency review plus the standing ability to fork, patch, and vendor. This is cheap at this dependency's size and is the honest cost of a single-maintainer package with 0 dependents.
Scaling
Rendering is CPU-bound and synchronous; the library adds negligible overhead relative to the base engine (expect single-digit percentage, not multiples). Real scaling concerns come from the base engine, not this package: TCPDF is memory-hungry with large embedded fonts and very long tables. For volume, generate on queued workers with explicit memory limits and timeouts, cache or pre-subset fonts, and keep generation out of the request cycle. Horizontal scaling is trivial because generation is stateless.
Failure modes to watch
phplib vs pdflib discrepancy). Pin and commit composer.lock.Ramp-up
Low for anyone who has touched FPDF. Documentation is genuinely above average for a package this small: separate docs/multicell.md and docs/table.md, plus runnable examples with committed PDFs and PNG previews — which is better onboarding than most 5-star packages offer. Estimate ~1 day for a competent PHP developer to be productive, and ~3–5 days to migrate a moderately complex document set including the subclass refactor. Assign a single owner; the knowledge is concentrated in one integration point and should not be diffuse.
Recommendation
Conditional go. Adopt as a targeted utility if FPDF/TCPDF is already the rendering stack and the recurring cost is rich text and paginated tables — the value is real and the integration is small. Do not adopt it as your PDF strategy if no engine has been chosen yet; evaluate HTML-based renderers first, because this package's ceiling is the base engine's fidelity, and choosing it commits you to a primitive-drawing API for every future document. Gate the decision on the Phase 0 spike and on confirming the package resolves and installs cleanly.
How can I help you explore Laravel packages today?