lidaa/twig-bundle
Lidaa Twig Bundle brings the Twig templating engine to Laravel. Render .twig views through Laravel's view system, configure template paths, caching, and extensions, and mix Twig and Blade where needed. A lightweight way to use Twig's syntax in Laravel apps.
What it actually is: lidaa/twig-bundle is a Symfony bundle, not a Laravel package. The brief frames it as "Laravel/PHP," but there is no service provider, no facade, no config/twig.php, and no Blade/Twig bridge for Laravel's view finder. It registers ~14 Twig extensions (php, image, url, css, js, tag, session, number, sf, unset, form, html, …) against Symfony's DI container via the twig.extension compiler tag. Architecture fit with our stated stack is poor at the distribution layer and merely adequate at the code layer. As a TPM, this reframes the decision: we are not buying a dependency, we are evaluating a reference implementation we may harvest from.
Integration feasibility, by extension:
css, js, tag, html, number, unset, url, image. These are thin, mostly stateless Twig extension classes. They can be lifted into a Laravel package with 1–2 days of rework each (swap Symfony's assets/router for Laravel's url()/asset()/Vite manifest).form (needs Symfony Form + form themes), session (typed against SessionInterface), sf (Symfony façade), and anything touching RequestStack or TranslatorInterface.php, which exposes php_function()/php_call() and converts every template into an arbitrary-code-execution surface. This is the package's headline feature and its single largest liability.Technical risk (TPM ranking):
| Risk | Severity | Why the TPM cares |
|---|---|---|
Security — php, unset, unbounded image paths |
High | Any CMS- or admin-editable template becomes an RCE/arbitrary-read vector. Creates a security-review gate before shipping. |
| Lifecycle / bus factor — 24★, 0 dependents, score 0.18 | High | No downstream validation, no issue triage, no advisory stream, no composer audit coverage. Assume zero upstream fixes. |
| Twig version drift | High | Extension inventory reads as Twig 1.x (getName(), initRuntime, Twig_Extension). Twig 3 removed these; several extensions likely need mechanical rewrites just to compile on Laravel's Twig 3. |
| Behavioral divergence (Symfony vs. Laravel semantics) | Medium | Ported helpers will "work" but emit wrong URLs, wrong session scoping, or different escaping. Surfaces late, in QA or prod. |
| Supply chain | Medium | Single maintainer, low signal. Vendor at a pinned commit hash or fork into the monorepo; never a semver range. |
Key questions before committing engineering time:
php, twig/twig, and symfony/* constraints — will any of it resolve on our PHP 8.2+/Twig 3 target without --ignore-platform-reqs?php opt-in or always-on? Is there a config toggle?Recommendation: do not install the bundle. Harvest the extension classes into an internal package. This is a reference-implementation decision, not a dependency decision, and it should be scoped and tracked as such.
Stack fit. Our target is Laravel (Blade-first, Twig optional via rcrowe/twigbridge). This bundle cannot be a runtime dependency of that stack — it will not boot. The only viable integration is source-level: copy the ported extension classes into an internal acme/twig-extras package that registers through a Laravel service provider and the twigbridge extension hook. This also lets us drop php and session entirely before anything reaches a template author.
Migration path.
twigbridge, and produce a per-extension verdict table: port / reimplement / drop. Output is a decision memo, not code.php, unset, image path handling. Written policy that php is not ported and template-editable files are out of scope for image.css, js, tag, html, number, unset, image, url — roughly 8–10 classes, rewritten against Laravel's url/asset/session facades. Skip form, session, sf (Symfony-coupled), and php (security).Compatibility. Two hard gates: (a) PHP 8.2+ / Twig 3 must compile the ported classes — if any extension depends on the Twig 1.x runtime-init model, budget extra rewrite time; (b) Laravel's twigbridge extension registration must accept them cleanly, otherwise we are maintaining a fork of the bridge too.
Sequencing. Land this alongside, not ahead of, the "Twig vs. Blade" product decision. If the organisation picks Blade, most of these helpers have no analogue and the package drops off the roadmap entirely. If Twig is chosen, this becomes a 3–4 week internal-library task — not a dependency onboard.
Maintenance. Once vendored, we own it. There is no upstream to patch, no security advisory coverage, and no realistic expectation that a 24★ / 0-dependent repo sees another commit. Budget a modest steady-state: ~1–2 days per quarter for Twig/Laravel upgrades, plus a rewrite every 12–18 months when the Twig extension model shifts. This is a recurring line item, not a one-off.
Support. No vendor, no SLA. Engineering owns every bug. The mitigation is scope discipline: keep the ported surface small (8–10 extensions), keep each class under ~50 lines, and keep them in a clearly owned internal package so that when the original repo disappears, we lose nothing but a link in a README.
Scaling. These are stateless, per-render helpers with negligible runtime cost — no scaling concern. The scaling concern is organisational: every new template author is another consumer of the API surface, and the php extension's absence needs to be a documented, enforced convention (template review, linter rule) rather than an unwritten one.
Failure modes to plan for:
php/unset during a "quick fix," the sandbox is defeated. Mitigation: CI check that the class does not exist in the internal package.url() vs. Symfony route generation produce different output; ported helpers pass unit tests but render wrong links in production. Mitigation: golden-file snapshot tests on rendered templates, not just on the helper.Ramp-up. Low for consumers — these are ergonomic helpers, a template author learns them in an afternoon. Higher for maintainers — the porting engineer needs Symfony-Twig and Laravel-Twig fluency to adjudicate which helpers are semantically correct on the target stack. Treat this as a one-engineer, one-sprint task with a security and a legal checkpoint, and expect ~60% of the bundle to be discarded as Symfony-coupled or security-unfit.
Bottom line for the portfolio: Approve this as a reference implementation for an internal Twig-extras package — bounded cost, bounded risk, clear owner. Do not onboard it as a third-party dependency of a Laravel application, and do not allow php or session to cross the boundary. The 24★ / 0-dependent / 0.18-profile signal is the correct read: useful as a pattern library, unsuitable as a platform commitment.
How can I help you explore Laravel packages today?