phpoffice/phpspreadsheet
PhpSpreadsheet is a pure PHP library for reading and writing spreadsheet files such as Excel and LibreOffice Calc. It provides a rich set of classes for working with workbooks, worksheets, formulas, and styling, making spreadsheet import, export, and manipulation straightforward in PHP applications.
Architecture fit. PhpSpreadsheet is an in-process, pure-PHP library — no daemon, no sidecar, no network hop. It installs via Composer into the Laravel application and executes synchronously inside the request or queue worker that calls it. That makes it a utility-tier dependency, not an architectural component: it should never appear in domain or controller code. The correct posture is an adapter behind a first-party interface (e.g. SpreadsheetWriter / TabularReader) so the library is a swappable implementation detail. If we skip that, every future migration (to a Go/Rust renderer, a document service, or a SaaS export API) becomes a codebase-wide refactor.
Integration feasibility. Low friction. Single MIT-licensed package, no transitive dependency conflicts typically, and the PHP floor (8.2 per README) is satisfied by any Laravel 11/12 target. The real feasibility check is the extension manifest, not Composer: ext-zip, ext-xml/ext-xmlreader, ext-mbstring, ext-iconv, and ext-gd for drawings/charts. These must be present in every environment — local, CI, staging, production container, and any serverless runtime we use. ext-gd in particular is commonly stripped from slim images and fails only at the moment a chart or image is embedded, i.e. in production, not in tests. Verify the Dockerfile and CI image before committing to a timeline.
Technical risk.
setReadDataOnly, read filters, row iteration, cell caching via a PSR-16 adapter, --memory-limit on workers) but they are design decisions we must make up front, not tuning we can defer.Key questions for the team.
Stack fit. Native Laravel fit via Composer autoload under PhpOffice\PhpSpreadsheet\*. Bind the adapter in a service provider; inject the interface, never the concrete class. Configuration (memory ceiling, temp path, default formats, formula policy) belongs in config/ with env overrides, not hardcoded in services. Queue integration: exports go through a job, write to object storage, and return a signed URL — do not stream large workbooks through the web request lifecycle.
Migration path. If PHPExcel is anywhere in the estate, the project ships an automated migration tool; the work is mostly namespacing and method renames, but typing changes under 2.0 mean static analysis will surface new errors. Budget a dedicated pass with PHPStan/Psalm enabled rather than a mechanical find-and-replace.
Compatibility. Pin a caret constraint on the current major and treat minor upgrades as reviewable PRs, gated by the golden-file suite. The PHP-version support policy is explicit (six months past upstream EOL), so our runtime upgrade calendar should be derived from their policy, not invented. Cross-platform: date serial handling (1900 vs 1904 epoch), locale decimal separators, and ICU version differences in number formatting are classic output-drift sources between dev machines and containers — pin the container image, not just the PHP version.
Sequencing.
Maintenance. Low ongoing cost if pinned and tested; the library is mature and releases are frequent and well-changelogged. The maintenance burden we own is the abstraction layer and the golden-file suite — that is the price of keeping the swap option open. Assign a named owner; this dependency will otherwise silently drift across majors.
Support model. Community-only: StackOverflow, docs, API reference, GitHub issues. No vendor SLA, no paid support tier. For anything business-critical, we need an internal runbook and the ability to read the source — which MIT permits. Key-person risk argues for a documented "vendor fork" contingency: clone, tag, patch. Keep that option cheap by not spreading library calls across the codebase.
Scaling. The library is stateless, so horizontal scale is straightforward: N queue workers, each bounded by memory_limit and a job timeout. The constraint is per-job resource envelope, not concurrency. Practical guidance: cap export size and paginate or split large workbooks into multiple files; move generation off the request path entirely; offload artifacts to object storage with TTL cleanup. Import workloads scale the same way, with an added per-file size cap and a dedicated low-privilege worker pool.
Failure modes to instrument and alert on.
=, +, -, @ emitted into files opened by downstream users.Ramp-up. The API surface is large but well-documented and idiomatic PHP; a mid-level engineer is productive on straightforward read/write within a day or two. The genuine ramp-up cost is spreadsheet semantics, not the library: number-format masks, date serials, style inheritance, merged cells, defined names. Budget for a short internal guide and the fixture suite as the team's shared reference. Expect the first non-trivial export (styling, formulas, multi-sheet) to take roughly 2–3× the estimate of someone who has only done CSV-style writes.
How can I help you explore Laravel packages today?