happyr/blaze-bundle
Symfony bundle for integrating the Blaze templating engine. It registers Blaze services, wires template configuration into Symfony, and lets you render lightweight templates from controllers and services with minimal setup.
Architecture fit — Poor (critical mismatch, unchanged by 2.0.0). happyr/blaze-bundle remains a Symfony bundle, not a Laravel package. Version 2.0.0 adds Symfony 5 and Twig 3 support — it makes the package more Symfony-native, not less. Bundles depend on the Symfony Kernel, config/bundles.php registration, the Symfony DI container, and compiler-pass/event-dispatcher wiring. A Laravel application has no bundle loader; its composition root is the service provider + Illuminate\Container. Nothing autoloads into a Laravel app as-is.
What 2.0.0 actually changes.
Functional scope — unchanged. "Entities to URLs" is domain-entity→route resolution. Laravel covers ~90% natively via route model binding ({post} → Post via getRouteKey()), route('posts.show', $post), and URL::signedRoute(). The residual is a thin convention layer: a HasCanonicalUrl-style interface plus a small resolver service.
Integration feasibility — Not feasible without a rewrite; 2.0.0 makes Composer resolution worse. To use this in Laravel you would still need to:
symfony/routing and symfony/http-foundation internally, but at ^6/^7 — a bundle declaring symfony/framework-bundle: ^5.0 will collide in the dependency graph. Expect a hard Composer conflict before any code runs.Effort for fork-and-port: 3–6 engineer-days plus permanent fork ownership, versus 1–3 days to build the equivalent natively. The 2.0.0 bump increases porting cost: the target API surface moved.
Technical risk — High (unchanged in kind, sharpened in detail).
symfony/* components.ContainerAwareInterface, YAML defaults, and deprecated APIs — each a latent runtime failure and each now a candidate for the 2.0.0 breaking changes.Key questions for the requester / engineering.
Verdict: Do not adopt — unchanged and reinforced. 2.0.0 does not add Laravel viability, does not lift the Symfony 5 ceiling, and introduces breaking changes with no migration guidance. Reimplement the mapping natively in Laravel (~200–400 LOC) behind a first-party interface. Recommended decision: reject dependency, accept requirement.
Stack fit — incompatible by construction; Composer now actively rejects it. Target stack: Laravel (PHP-FPM/Octane, Composer, service providers, Eloquent, Blade). Package targets Symfony (Kernel, bundles, DI extension, YAML service config) and now Twig 3 templates. There is no supported bridge and no shared extension point. Treat the package as reference implementation only — read the 2.0.0 sources for the entity→route convention, then discard the code.
Target design in Laravel (recommended path, unchanged).
| Need | Laravel-native primitive |
|---|---|
| Entity → canonical URL | route('posts.show', $post) + route model binding |
| Polymorphic entity → URL | Interface HasCanonicalUrl { public function canonicalUrl(): string; } per model; resolver maps type → route name |
| Custom route keys (slug) | getRouteKeyName() |
| Signed / expiring links | URL::signedRoute() / temporarySignedRoute() |
| Inbound URL → entity | Implicit/explicit route model binding, Route::bind() |
| Localized URLs | route('posts.show', ['post' => $post, 'locale' => app()->getLocale()]) |
| Rendering links in views | Blade component/directive (replaces the Twig extension surface) |
A single CanonicalUrlResolver bound in AppServiceProvider (or a small first-party package under packages/) covers the gap. Keep it interface-typed so a maintained third-party option can be swapped in later.
Migration path. Nothing to migrate from in a Laravel codebase — no call sites can exist. If a Symfony service uses it:
^2.0.0 explicitly (the 1.x→2.x jump is breaking), document as legacy, and freeze.HasCanonicalUrl; mirror the bundle's output with golden-file parity tests comparing generated URLs across every entity type.Compatibility considerations (must-do before any fork is approved).
symfony/routing, symfony/http-foundation, symfony/console, symfony/process, symfony/var-dumper (^6/^7). Overriding these constraints is a whole-app risk, not a package-local one.ContainerAwareInterface, YAML defaults, services.yaml semantics) are the likely breakage points if we ever port.twig/twig into a Blade application — dead weight on the autoloader and a second supply-chain surface.Sequencing (4-week shape).
HasCanonicalUrl + resolver + Blade component + tests; signed-URL helper if needed. Publish as an internal package if more than one app consumes it.happyr/blaze-bundle and explicitly noting that 2.0.0 was reviewed and does not change the decision. Onboarding note for the resolver.Explicit non-goal: do not boot a Symfony Kernel inside Laravel, shim bundle registration, or add Twig alongside Blade to reach the bundle's rendering path. The maintenance cost and failure surface exceed the value of the few hundred lines it replaces.
Maintenance — Low on the native path; High on any fork, and 2.0.0 raises fork cost. Native implementation is small, understood, test-covered, and evolves with Laravel upgrades. Forking an EOL-framework bundle makes us the permanent maintainer of someone else's code with no upstream to rebase against — and the 2.0.0 breaking changes mean our port baseline is now a moving target that moved exactly once in five years. Prefer owning 300 lines we wrote over 3,000 we inherited.
Support — None. No vendor, no SLA, no active maintainer, 0 dependents to consult. A one-line 2.0.0 release note is not a support channel and provides no security response path. Internal support model must be "the team that wrote the resolver." Document the resolver in the platform runbook; assign a code owner.
Scaling — Neutral, with the same caveat. URL generation is cheap and stateless; volume impact is negligible either way. The real risk is context dependence: URL generation in queue workers, scheduled commands, or Octane workers fails when a resolver assumes request context. Design the resolver to take an explicit base URL or read config('app.url'), and test it under queue and Octane. Symfony's RequestStack-based approach can bind to the wrong request under Octane — a failure mode we inherit for free by porting.
Failure modes to design against.
| Failure | Cause | Mitigation |
|---|---|---|
| Composer install/update fails | Symfony 5 constraint vs. Laravel's symfony/* ^6/^7 |
N/A on native path; constraint override + fork if ever forced |
| Port drifts from upstream | 2.0.0 breaking changes with no changelog | Pin ^2.0.0, snapshot sources, treat as frozen reference |
| 500 on URL generation | Unregistered entity type / missing route name | Typed exception + registry map, unit-tested per model |
| Wrong host/port in links | Request-context capture in queue/CLI | Explicit base URL config; test in job context |
| Broken links after route rename | Convention coupling between route names and entities | Central route-name registry; route-list snapshot test |
| Cache poisoning of resolutions | Caching entity→URL without invalidation on slug change | Key on updated_at/slug; invalidate on model save |
| Blade/Twig parity gap | Twig-only rendering path in the bundle | Reimplement in Blade as part of parity tests, not after |
| Bloat / duplicate templating engine | Pulling twig/twig transitively |
Do not install; native path has no Twig dependency |
Ramp-up — Low. A Laravel engineer absorbs a 200–400 LOC resolver plus an interface in under a day; route model binding and the service container are already familiar. The bundle path requires learning Symfony bundle conventions, DI extension semantics, Twig extension points, and a bespoke port — roughly 3–5 days for a component whose entire value is URL string assembly. The 2.0.0 release adds a breaking-change review on top of that. That asymmetry is the strongest argument for the native route.
Overall risk posture. Adoption: high technical risk, negative ROI, no support path, and — as of 2.0.0 — a confirmed ceiling at EOL Symfony 5. Rejection + native build: low risk, small bounded cost, full ownership. Record in the ADR that 2.0.0 (Symfony 5 / Twig 3) was evaluated and does not alter the decision, so the question does not resurface at the next release.
How can I help you explore Laravel packages today?