em411/feature-flag-bundle
A Symfony bundle for feature flags: enable or disable code paths based on context-aware callables. This is a Symfony 4.4 / PHP 7.4 backport of ajgarlag/feature-flag-bundle, keeping the same API and namespace for a drop-in upgrade from the upstream package.
if ($config->get('feature_x')) service or a commercial flag platform. This package sits in between: MIT licensed, no runtime dependency beyond the framework, and it provides the service wiring, Twig helpers, and a profiler panel that an in-house implementation would take a sprint or two to reach parity on.Ajgarlag\FeatureFlagBundle\ namespace. That makes the eventual Symfony 6+/PHP 8 upgrade a Composer constraint change rather than a code rewrite. A PM can treat this as a bridge dependency with a known, near-zero-cost exit — which is a much easier thing to get approved than a custom abstraction.ProviderInterface rather than hard-coded booleans, the choice of where flag state lives (config, Doctrine, Unleash/GitLab, LaunchDarkly) stays reversible. This lets a PM defer the "which flag platform do we standardise on" decision without blocking feature delivery.@AsFeature("xmas") example is a genuine, if small, product use case.Adopt it when all of the following are true:
ServiceProvider/ChainProvider handle the in-process cases; anything stateful is your code.audit.block-insecure in CI, and flags this trade-off in the changelog. That is honest, but it is a decision someone owns.kernel.controller listener level. Symfony 4.4 cannot evaluate services in route condition expressions, so there is no declarative route gating here.Look elsewhere when:
ajgarlag/feature-flag-bundle directly; it uses native PHP 8 attributes and is actively targeted at modern Symfony. This fork is strictly the legacy path.@AsFeature Doctrine annotation, which cannot be repeated on the same class or method. Multiple flags on one class require falling back to the ajgarlag.feature_flag.feature service tag — a papercut that will annoy teams with flag-heavy services.ProviderInterface is possible but is a product in itself.One line: a small, MIT-licensed Symfony bundle that lets a legacy Symfony 4.4 application ship features behind toggles — cheap to adopt, cheap to leave.
For executives: this is not a platform investment. It is a tactical enabler that costs roughly a Composer line and a config entry, and it buys the organisation the ability to release code without immediately exposing it to customers — the minimum prerequisite for canary releases and kill switches. There is no licence fee, no data leaving our infrastructure, and no lock-in: the API is intentionally identical to a maintained upstream package, so when we upgrade off Symfony 4.4 the migration is a version constraint, not a rewrite. The risks are equally small and equally clear: a single maintainer, essentially zero community, and a stack that is already end-of-life. We should adopt it as scaffolding with a documented exit, and we should not build product commitments that assume flag-management features (targeting rules, experiments, admin UI) it does not have.
For engineering: FeatureCheckerInterface is the seam — inject it, and wrap it in an application-level interface so swapping to upstream or a vendor SDK later is a single adapter class. Prefer providers over hard-coded callables so flag state stays external to the binary. The Twig helpers (feature_is_enabled, feature_get_value) keep conditional UI out of controllers, and the web profiler collector gives per-request visibility into resolved values, which is the difference between a debuggable rollout and a guessing game. Budget the papercuts: annotation-only declarations, no repeatable annotations, and controller-level rather than route-level gating.
Decision requested: approve as a time-boxed bridge dependency tied to the Symfony 4.4 → modern-stack upgrade, with an owner, an exit criterion, and an explicit instruction to route all flag access through one application-level interface.
How can I help you explore Laravel packages today?