indragunawan/facade-bundle
A Laravel package that bundles a set of ready-to-use facades, giving you concise static access to commonly used services and helpers. Reduce boilerplate imports and keep your code clean with simple, consistent facade calls.
Architecture fit — poor-to-conditional (unchanged). v0.2.0 adds Symfony 5 compatibility; it does not change what the package is. It ports Laravel's Facade pattern (static proxy over a container-managed service) into Symfony, which is architecturally backwards for the target stack: Symfony's convention is explicit constructor injection, and facades reintroduce a service-locator that hides dependencies from the call graph, the container's compile-time validation, and static analysis (PHPStan/Psalm). It remains defensible only as a narrow migration escape hatch — e.g. moving a Laravel-trained team or a legacy procedural codebase onto Symfony services without rewriting every call site at once.
Integration feasibility — mechanically simple, politically costly (unchanged). Enablement is a composer require, a bundle registration in config/bundles.php, and per-facade classes extending the package's base facade with an accessor returning a service ID. A competent Symfony developer can spike this in under a day. The cost is not implementation, it is the precedent: once Foo::bar() works, injection discipline erodes and code review has to enforce a boundary the framework would otherwise enforce for free.
Technical risk — still high, but the risk profile has shifted from "abandoned" to "unproven and thin." v0.2.0 is the first release in over four years, and its entire changelog is a single line: "Symfony 5 compatibility." That is a meaningful but narrow signal. It reduces the probability that the package is dead, and it raises the ceiling of the supported envelope from Symfoy 4.4-era to Symfony 5 — but nothing more.
ContainerAwareInterface/ContainerAwareTrait (deprecated in 4.4, removed in 6), a Symfony 6/7 migration requires a fork on day one. A one-line "Symfony 5 compatibility" note is equally consistent with a genuine refactor and with a composer.json constraint bump, so the diff, not the changelog, is the source of truth.Key questions. (1) Is v0.2.0 a real compatibility change or a constraint bump — and does the code still reference ContainerAware*? (2) Does the package now run on the Symfony version we actually target, or does "Symfony 5" mean we are adopting an EOL framework line to use it? (3) Does this release signal resumed maintenance, or is it a one-off to unblock a downstream user? (4) What is the actual scope — a handful of adapter classes, or an open invitation across the codebase? (5) Does the target runtime use long-running workers? (6) Who owns the fork, and what is our patch SLA for a PHP/Symfony major bump? (7) Is the real requirement "Laravel-style ergonomics for onboarding" — in which case a 60-line in-house facade is still cheaper than an external dependency.
Stack fit. Treat Symfony 4.4/5.x and PHP 7.4–8.0 as the confirmed supported envelope — that is precisely what v0.2.0 buys us and no more. Validate with composer why-not indragunawan/facade-bundle <symfony version> and a throwaway container boot on the actual target version before any planning commitment. If the target is Symfony 6/7, v0.2.0 does not change the answer.
Migration path. Do not depend on the upstream package as a production-critical library. Preferred order:
dev- branch internally, and treat it as first-party code we own. If we fork, branch from the v0.2.0 tag, not from the 2020 code, so we inherit whatever Symfony 5 fixes were made.ServiceSubscriberInterface-backed locator is tens of lines and removes the supply-chain question entirely. Given the minimal dependent base, this is usually the cheaper option, and v0.2.0 makes it cheaper still by demonstrating how small the maintenance surface actually is.src/Legacy/Facade/) so a future removal is a mechanical delete rather than an archaeology project.Compatibility. Read the v0.1.x..v0.2.0 diff before anything else: confirm whether composer.json platform constraints were widened to PHP 8.x, whether ContainerAwareInterface/Trait was removed, and whether any behaviour changed (a facade base-class signature change would be a silent breaking change for any inherited classes). Then run the Symfony deprecation helper at max verbosity on the spike branch; confirm compiler passes still register on the target kernel; add a CI job that boots the kernel and asserts each facade resolves. Add PHPStan/Psalm at a level that at least catches undefined facade methods — static calls are exactly what these tools miss by default, so a custom baseline rule is needed.
Sequencing. (a) Two-day spike on the real Symfony version, boot + one facade + one call site, using v0.2.0; (b) diff review and go/no-go on fork vs. in-house; (c) restrict to the migration scope, with a documented list of permitted facade classes; (d) add a static-analysis or code-review rule blocking new facade usage outside that directory; (e) write the deprecation/exit plan before the first merge, not after. Add (f): a re-evaluation trigger — re-assess if upstream ships a Symfony 6/7 release or if 12 months pass without one.
Maintenance. Still assume no reliable cadence: one release in over four years, single maintainer, no security-policy file. v0.2.0 is evidence the maintainer can still ship, not evidence of a support contract. Budget an internal owner and a recurring line item for major-version bumps — and note the bump we need (Symfony 6/7) is not one upstream has signalled. Pin to the v0.2.0 tag explicitly; do not float on dev-main hoping for follow-through. Our fork remains the maintenance plan.
Support. No community, no CVE feed, no issue triage. Incident response for anything traced to facade resolution is entirely internal, and the failure signature (a RuntimeException from a static call) is unfamiliar to most Symfony on-call engineers. Document the resolution path in the runbook.
Scaling. Per-call cost is negligible — one container lookup, cached after first resolution — so throughput is not the concern. The concern is state: static registries are process-global, so under FrankenPHP worker mode, RoadRunner, or Swoole the registry and any cached resolutions survive across requests. v0.2.0 does not touch this. Verify reset semantics (kernel reboot hooks) or forbid the bundle in worker-mode deployments.
Failure modes. Facade not registered → runtime exception at the call site rather than at boot; container unavailable in CLI/worker contexts → resolution failure in code paths that previously worked; service ID renamed in services.yaml → silent breakage found in production; circular service references surfaced only when the facade is first called; preloading/opcache edge cases with dynamically registered classes; and, specific to this release, any base-facade or registration API change in v0.2.0 that we inherit silently when we bump. None of these are caught by the container's compile-time graph, which is the whole point of Symfony's DI.
Ramp-up. Asymmetric and unchanged. Laravel-background engineers ramp in minutes; Symfony-native engineers will actively resist it, and reviewers must arbitrate. The Symfony 5 compatibility bump makes the tool easier to install without making it easier to defend. Expect a durable "two DI paradigms" tax in onboarding docs and code-review throughput, and size the migration effort accordingly — the tool is cheap, the convention debt is not.
How can I help you explore Laravel packages today?