Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Twig Spreadsheet Bundle Laravel Package

erelke/twig-spreadsheet-bundle

Symfony bundle that integrates PhpSpreadsheet with Twig, letting you build spreadsheets from templates with macro and include support. Exports to XLSX, XLS, ODS, CSV, and PDF via mPDF.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Framing correction up front. This is not a Laravel package. erelke/TwigSpreadsheetBundle is a Symfony bundle — it registers a DI extension, a compiler pass, and services into the Symfony container, and depends on symfony/framework-bundle, twig/twig, and phpoffice/phpspreadsheet. Laravel will not auto-discover or boot it. That mismatch is the single largest architectural fact in this assessment and it reframes the evaluation from "should we composer require this" to "is this codebase a useful reference we should mine."

Architecture fit. The package's actual value is one idea: it lets a spreadsheet file serve as the layout template, with Twig rendered into cells rather than into HTML. That is genuinely valuable for finance/ops reporting where stakeholders author the visual layout in Excel (fonts, merged cells, column widths, print areas) and engineers only supply the data bindings. The Twig macro/include support means reusable cell snippets and header blocks. None of that is Symfony-specific in principle — the rendering pipeline is PhpSpreadsheet reader → cell-range iteration → Twig environment → writer. Only the wiring is Symfony-shaped.

Integration feasibility. Low as a dependency, moderate as a reimplementation. Installing it into Laravel means fighting bundle registration, the Symfony event dispatcher integration, and a 2021-era service definition file. The realistic path is extraction: read the bundle's service classes (likely a template loader, a spreadsheet renderer, and a format-selection layer), port the logic into a Laravel service provider, and use twigbridge if you want Twig in Laravel — or rewrite the binding layer onto Blade. The surface area is probably a few hundred lines, not thousands, so this is a 1–3 day spike, not a project.

Technical risk: high, on multiple axes.

  • Abandonment. Last release 2021-04-10. Travis CI badges indicate builds that stopped running when Travis' OSS tier collapsed — the green badges are historical artifacts, not evidence of health. Zero dependent packages means zero downstream pressure to fix anything and no community fork to inherit.
  • Adoption signal. 2 stars, 0 dependents. This is not a package anyone has validated in production. Scanner scores (3.85 / opportunity 26.46) are picking up structure — README, changelog, releases, license — not trust.
  • Version drift. README declares PHP 7.1+ / Symfony 3.4+. PhpSpreadsheet has since shipped 2.x and 3.x with breaking changes to writers, style APIs, and reader behavior. Twig 3.x changed include() semantics and autoescaping defaults. Symfony 6/7 removed the container APIs a 2021 bundle compiled against. Assume it does not run on a current stack without patching.
  • CSV/formula injection. Any template engine that writes user data into spreadsheet cells is a formula-injection vector (=, +, -, @ prefixes executing on open). There is no indication this bundle sanitizes, and an abandoned package will never get that patch.
  • Binary templates. The template-is-a-spreadsheet model puts .xlsx artifacts in git. Reviewing diffs is impossible; a designer's styling change is an opaque binary commit.

Key questions for the maintainer/spike owner:

  1. Does the bundle boot and render at all on PHP 8.2/8.3, Twig 3, PhpSpreadsheet 2.x? What breaks, and how many lines to fix?
  2. What is the actual line count of the non-Symfony rendering logic? If it's small, extraction beats dependency.
  3. Do we need formulas preserved live in output, or static values? (Live formulas mean the recipient's Excel recalculates — different template design.)
  4. Which formats are in scope — xlsx only, or CSV/PDF too? PDF via mPDF is a separate, heavy dependency with its own memory profile.
  5. Are template authors business users or engineers? That determines whether the Twig layer is worth reproducing at all.
  6. Is there a maintained fork or successor? Search GitHub forks and Packagist before concluding no.

Integration Approach

Stack fit. Poor as-is, workable as a pattern. Laravel + Blade is the house stack; introducing Twig at all is a second templating language and a permanent cognitive tax. The pragmatic middle is: keep PhpSpreadsheet (actively maintained, MIT, the real engine), keep Blade for the data layer, and implement the spreadsheet-as-template concept natively — load a .xlsx template, walk a named-range or placeholder map, write values, stream the output.

Migration path. Three options ranked:

  1. Recommended — build internal. A SpreadsheetTemplate service in our app: PhpSpreadsheet\IOFactory::load() a template, resolve {{ token }} placeholders per cell, write via Xlsx writer. 2–4 days, full ownership, no Twig, no dead dependency, and we control the injection sanitizer.
  2. Acceptable — extract the package's logic. Vendor the renderer classes, strip Symfony DI, wire through a Laravel service provider, keep Twig only if the team genuinely wants it. Faster to first output, but we now maintain a fork of code we didn't write and don't understand.
  3. Not recommended — install the bundle. Would require dusterio/laravel-symfony-style shims or a Symfony sidecar; cost exceeds the value for a feature this narrow.

Compatibility. If we do any extraction, pin explicit versions: PHP 8.2, phpoffice/phpspreadsheet ^2 (or ^3), twig/twig ^3. Budget a half-day for API drift on the writer and style calls. Do not inherit the bundle's composer.json constraints.

Sequencing.

  1. Day 1: spike — attempt the bundle in a throwaway Symfony app or Laravel+twigbridge to confirm the concept works and to read the code. Timebox hard.
  2. Day 1: capture the design — how placeholders are declared, how macros/includes map to cells, how format is selected — as a spec, not as code.
  3. Day 2–3: implement option 1 against the spec, with a named-range placeholder convention (rpt_header, rpt_total) instead of raw cell coordinates so templates survive row insertions.
  4. Day 4: golden-file regression suite — render a fixture template, unzip the xlsx, assert on sheet XML for values and on styles for formatting. This is the only way to catch silent styling regressions.
  5. Day 5: queue integration, memory guardrails, and a formula-injection sanitizer on every user-supplied string cell.

Ship behind a feature flag; keep the Symfony bundle out of composer.json entirely.

Operational Impact

Maintenance. If we adopt the dependency: the burden is 100% ours from day one — no upstream patches, no security response, no PHP 9 readiness. That is a standing liability for a feature that generates reports. If we build option 1: the burden is normal — we own ~300 lines of our own, well-tested code, on a maintained engine. The build option is less maintenance despite more initial work; this is the central TPM judgment here.

Support. No vendor, no maintainer responsiveness, no issue triage. Internal support means whoever wrote the extraction owns it. Document the placeholder convention in a README and keep a sample template in the repo — otherwise template authoring becomes an oral tradition and the bus factor is 1.

Scaling. PhpSpreadsheet holds the full workbook object graph in memory — roughly 1KB+ per cell with styles. A 50k-row × 20-column export is a memory incident waiting to happen. Concretely: cap synchronous generation at ~5k rows, push anything larger to a queue worker with its own memory limit, and for genuinely large exports switch to a streaming writer (OpenSpout) or offer CSV instead of xlsx. Twig rendering into cells adds a per-cell template evaluation cost on top — benchmark at 10k cells before committing to the templating approach for high-volume reports. Set memory_limit and a hard row ceiling in config, and fail loudly rather than OOM-killing the worker.

Failure modes to instrument:

  • Memory exhaustion mid-write → truncated/corrupt file delivered to a user. Serve downloads only after the file is fully written and fsync'd; write to temp then move.
  • Template drift: a business user edits the .xlsx template and removes a named range → runtime null-reference. Validate template structure on upload, not at generation time.
  • Formula/CSV injection on exported user strings — sanitize and test for it explicitly.
  • Locale and date handling: PhpSpreadsheet writes serial dates; recipients in another locale see wrong formatting. Pin timezone and date format at write time.
  • PDF path: mPDF is memory-hungry and font-bundle-heavy; treat PDF as a separate, separately-monitored job, not a toggle on the xlsx job.
  • Silent style loss on PhpSpreadsheet major upgrades — golden-file tests are the control.

Ramp-up. The engine (PhpSpreadsheet) is well documented; a mid-level Laravel dev reaches productive output in 2–3 days. The template-authoring workflow is the real ramp: business users need a one-page guide to placeholder placement, and engineers need to internalize that layout lives in a binary artifact under version control. If we go the Twig route, add a day for developers who've never used Twig's macro/include and for the escaping model — Twig's autoescape defaults interacting with spreadsheet cell content is a subtle source of double-escaped output.

Verdict. Do not take the dependency. Two stars, zero dependents, five years stale, and the wrong framework for our stack is enough to disqualify it as a composer require. Treat it as a well-scoped reference design, harvest the spreadsheet-as-Twig-template concept, and implement it in ~a week on PhpSpreadsheet with Blade and our own sanitization. Revisit only if a maintained fork appears with active CI on PHP 8.3+.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log