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

motoronix/twig-spreadsheet-bundle

Motoronix Twig Spreadsheet Bundle brings Twig templating to spreadsheet generation in Symfony, letting you define Excel and CSV exports as reusable Twig templates and render them from your controllers or services, skipping manual PHP spreadsheet code. Ideal for reports and data exports.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What the package actually is. motoronix/twig-spreadsheet-bundle is a Symfony bundle, not a Laravel package. Its purpose is narrow and useful-sounding: expose PhpSpreadsheet through Twig so that spreadsheet workbooks (XLSX/CSV) can be authored as templates — cell values, merges, styles, and loops declared in a .twig file — rather than built imperatively in PHP. The real engine is phpoffice/phpspreadsheet; this bundle is an authoring/rendering convenience layer on top of it.

Architecture fit. Poor for a Laravel codebase. A Symfony bundle is a packaging convention bound to Symfony's Kernel, DI extension (DependencyInjection/*Extension.php), service tagging, bundle config trees (Configuration.php), and typically Symfony HTTP response classes (StreamedResponse/Response) for downloads. Laravel has no bundle registration mechanism; none of that wiring is reused. What is reusable is the Twig extension layer (the filters/functions/tags that map Twig nodes onto PhpSpreadsheet API calls) — and that layer is coupled to Twig's ExtensionInterface and Environment, which Laravel does not ship.

Integration feasibility. Two viable shapes:

  1. Full adoption: add rcrowe/twigbridge to Laravel, configure a second template engine, register the bundle's Twig extensions manually in a service provider. This is achievable but introduces a permanent second templating engine, a second set of escaping/autoescape semantics, and a bundle whose service definitions assume Symfony's container semantics (constructor autowiring by type, parameter bags, no Laravel facades). Expect to write shims and to patch the bundle's service definitions out of the picture entirely.
  2. Selective vendoring: MIT license permits copying the Twig extension classes and the renderer into app/Spreadsheet/, stripping the Symfony DI glue. This is usually the correct answer and changes the risk calculus from "dependency on an unmaintained package" to "dependency on ~a few hundred lines of copied code we now own."

Technical risk. High, and mostly supply chain, not capability:

  • 0 stars, 0 dependents, single maintainer. No downstream validation, no visible issue triage, no evidence of a release cadence or SemVer discipline, no security disclosure path.
  • Fork provenance. Packages in this niche are frequently forks of the older spreadsheet-bundle/TwigSpreadsheetBundle lineage. A TPM should assume fork provenance until proven otherwise and check whether upstream fixes are being merged forward.
  • PhpSpreadsheet is a fast-moving, high-churn dependency. It has made breaking changes across majors (writer APIs, IOFactory, style/conditional-formatting objects, PHP version floors). A thin, low-traffic wrapper is exactly the kind of package that silently pins an old major and blocks your own security patching of PhpSpreadsheet.
  • No composer.json constraints visible at scoring time means the PHP/Symfony/PhpSpreadsheet version matrix is unverified. Symfony 5→6→7 bundle base-class changes (Bundle vs AbstractBundle, return types on extension methods) break thin bundles routinely.
  • Blast radius if it fails is contained: worst case you delete the dependency and call PhpSpreadsheet directly. That is a genuine mitigating factor — this is an authoring convenience, not a data-plane component.

Key questions before any pilot:

  • Which phpoffice/phpspreadsheet major is required, and can it be widened without patching? Does it conflict with the version our other tooling needs?
  • Which Symfony major, which PHP floor? Does the bundle base class still exist in the Symfony version implied?
  • Is this a fork of spreadsheet-bundle/spreadsheet-bundle? If so, what has diverged, and are upstream fixes being pulled?
  • Is there a test suite? Do the tests cover the Twig tag/filter surface, or only the happy path of a single template?
  • Does the renderer stream to php://output or build the whole workbook in memory? (This determines whether large exports are safe.)
  • Does it emit CSV/XLSX as a download response — and does it sanitize leading =, +, -, @ in user-supplied cell values (CSV/formula injection)?
  • What is the maintenance commitment? If it's one person's side project, we need a named internal owner before adopting.
  • Is the Twig DSL expressive enough to cover our real templates (loops, conditional styling, multi-sheet, images, named ranges, freeze panes), or will we be fighting it within two sprints?

Integration Approach

Stack fit. The stack fit is conceptually good and mechanically awkward. Conceptually, template-authored spreadsheets are a strong fit for a product where finance/ops stakeholders own report layouts: a Twig file in version control is reviewable, diffable, and editable by non-PHP staff in a way that a 400-line SpreadsheetExport class is not. Mechanically, Laravel + Twig is a mismatch: Blade is the sanctioned engine, Twig needs a bridge, and now every developer must know both. That is a real, recurring cost that should be priced in.

Recommended approach: don't add it as a Composer dependency. Vendor the Twig-extension and renderer classes into the application under app/Support/Spreadsheet/, wrapped behind our own interface:

SpreadsheetRenderer::render(string $template, array $context): StreamedDownload

Backed initially by the vendored Twig extensions; trivially re-implementable with Blade directives + direct PhpSpreadsheet calls if the DSL proves unnecessary. This preserves the one thing the package offers (declarative templates) while removing the abandonment risk, the Symfony-container shims, and the version-pin problem. Keep the MIT header intact and record the source commit in the file docblock for provenance.

Migration path. If an existing Symfony service already uses this bundle, do not lift-and-shift the templates and the bundle simultaneously. Sequence:

  1. Inventory existing .twig spreadsheet templates; classify by feature usage (does anything use images, charts, conditional formats, or multi-sheet loops?).
  2. Port the engine first, templates second: stand up the vendored renderer inside Laravel and prove it renders the two most complex existing templates byte-comparably against the Symfony output. Byte comparison is the only cheap regression test you'll get here.
  3. Move templates, one per PR, with a golden-file test each.
  4. Retire the bundle entirely; the Twig bridge, if used, stays only for as long as spreadsheet templates exist — ideally not at all.

Compatibility. Pin PhpSpreadsheet explicitly in our own composer.json and let the vendored code adapt to it, not the reverse. Watch: PHP floor (PhpSpreadsheet has moved its minimum PHP version forward repeatedly), ext-zip and ext-gd/ext-fileinfo availability across our container images and CI, and memory limits in php.ini for the CLI/queue workers that will actually do the rendering.

Sequencing. Timebox a spike (2–3 days) that answers only: (a) does the Twig DSL cover our top-5 report templates, (b) what PhpSpreadsheet version does it force, (c) how many lines of Symfony glue must be removed to make it run in Laravel. If the answer to (c) exceeds a few hundred lines or (a) requires extending the DSL, stop and build directly on PhpSpreadsheet — at that point the package is contributing negative value. Defer the Twig bridge decision until after the spike; if the DSL is dropped, so is the bridge.

Operational Impact

Maintenance. With vendored code, maintenance is a known, bounded internal cost: we own the Twig extension surface (~small), and we own the upgrade work when PhpSpreadsheet majors. With the dependency, maintenance is unbounded and externalized — a zero-star package with no release cadence will either go silent (forcing urgent vendoring later, under pressure) or publish breaking changes without migration notes. The vendored path is more work now and strictly less work later. Budget roughly one engineer-day per PhpSpreadsheet major bump either way.

Support. There is effectively no support channel. No dependents means no Stack Overflow corpus, no blog posts, no one else's bug reports to read. Every question becomes a read-the-source exercise. The upstream to lean on is PhpSpreadsheet's documentation and its own issue tracker, which is genuinely good — another argument for keeping the coupling to PhpSpreadsheet direct and the coupling to this bundle loose.

Scaling. The bottleneck is never the bundle, it is PhpSpreadsheet: cell-by-cell object graph in memory, roughly ~1KB per cell as a working estimate. A 50k-row × 20-column export is ~1M cells and will exhaust a 512MB worker. Implications:

  • Never render large workbooks in the request/response cycle. Route exports through a queued job, write to object storage, notify or poll.
  • Set memory_limit on the queue worker explicitly, and treat OOM as an expected, retryable failure rather than an incident.
  • Use the Xlsx writer with a temp file and setPreCalculateFormulas(false); avoid IOFactory auto-detection on our own output.
  • The bundle's Twig indirection adds parse/render overhead per file (typically negligible relative to PhpSpreadsheet) but means templates are compiled — cache the Twig environment, and do not re-instantiate it per row.

Failure modes to instrument and alert on:

  • Memory exhaustion on large exports — most common by a wide margin; needs a per-export row cap and a clear user-facing error.
  • Template drift — a finance-owned .twig template edited without a golden-file test will silently shift columns. Mitigate with byte-comparison tests against committed fixtures.
  • Formula/CSV injection — user-controlled values beginning =, +, -, @, \t, \r must be written as explicit strings (setCellValueExplicit(..., DataType::TYPE_STRING)), not inferred. Verify the vendored code does this and add it if not; this is a security finding, not a nicety.
  • Encoding and locale — UTF-8 BOM handling on CSV, and date/number formats written as strings rather than real serial dates. Both produce files that open fine and are wrong. Golden-file tests catch these; nobody notices in manual QA.
  • Dependency pin collision — a composer update elsewhere in the app forces a PhpSpreadsheet downgrade and spreadsheet generation breaks in a way unrelated to the change that triggered it. Lock PhpSpreadsheet explicitly and put an integration test in CI that actually writes a workbook.
  • Abandonment — if left as a dependency, the failure is a future forced migration. Track it: if the upstream repo shows no commit for 12 months, schedule the vendoring work.

Ramp-up. Low for anyone who knows Twig and has seen a templating engine (hours to productive, a day to understand the spreadsheet-specific tags and style objects). Higher for a Blade-only team, because the cost is not this package but Twig itself — a second engine with different autoescape rules, different filter syntax, and different debugging ergonomics. If the team is Blade-native and the number of spreadsheet templates is small (under ~5), skip Twig entirely: write the exports imperatively against PhpSpreadsheet behind a SpreadsheetRenderer interface, and revisit template authoring only when a non-engineer genuinely needs to own a layout. Document the DSL for whoever inherits it, and keep a single worked example template next to the renderer — with zero community examples available, that in-repo example is the entire onboarding path.

Bottom line for the decision log. The idea — declarative spreadsheet templates — is worth adopting. This specific package is not a safe runtime dependency at 0 stars, 0 dependents, and unverified version constraints. Vendor the MIT-licensed Twig extensions behind our own interface, pin PhpSpreadsheet ourselves, render on a queue, and prove correctness with golden-file tests. If the spike shows the DSL doesn't cover our templates, drop it without regret and call PhpSpreadsheet directly — the export engine is doing all the real work either way.

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.
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
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator