twentytwo-labs / feature-flag-bundle
Bundle to manage features flag
Installs: 372
Dependents: 2
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Type:symfony-bundle
Requires
- php: >= 8.1
- ext-json: *
- symfony/expression-language: ^5.4|^6.0|^7.0
- symfony/framework-bundle: ^5.4|^6.0|^7.0
- symfony/options-resolver: ^5.4|^6.0|^7.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- infection/infection: ^0.29
- matthiasnoback/symfony-dependency-injection-test: ^5.0
- phpstan/phpstan: ^1.11
- phpunit/phpunit: ^10.0
- squizlabs/php_codesniffer: ^3.10
- symfony/security-bundle: ^5.4|^6.0|^7.0
- twig/twig: ^2.0|^3.0
This package is auto-updated.
Last update: 2025-03-01 00:40:41 UTC
README
The FeatureFlagBundle is a bundle to manage features flags in your Symfony applications.
Compatibility
This bundle is tested with at least all maintained Symfony version.
Documentation
Install it
Install extension using composer:
composer require twentytwo-labs/feature-flag-bundle
If you don't use Flex, enable the bundle in your config/bundles.php
file:
<?php return [ // ... TwentytwoLabs\FeatureFlagBundle\TwentytwoLabsFeatureFlagBundle::class => ['all' => true], ];
Configuration
To configure and register a feature manager you need a factory service. You may also need to change some options to the factory.
# ... twentytwo_labs_feature_flag: managers: default: factory: 'twenty-two-labs.feature-flags.factory.array' options: features: my_feature_1: false my_feature_2: true my_feature3: '%env(bool:FEATURE_ENVVAR)%'
The factories that come with this bundle can be found in the table below.
Factory service id | How to Install |
---|---|
twenty-two-labs.feature-flags.factory.orm | composer require twentytwo-labs/orm-feature-flag |
twenty-two-labs.feature-flags.factory.api-service | composer require twentytwo-labs/api-service-feature-flag |
Example configuration
# ... twentytwo_labs_feature_flag: managers: default: factory: twenty-two-labs.feature-flags.factory.array options: features: my_feature_1: enabled: false description: MyFeature1 description text my_feature_2: enabled: true description: MyFeature2 description text expression: "is_granted('ROLE_ADMIN')" my_feature3: enabled: '%env(bool:FEATURE_ENVVAR)%' description: MyFeature3 description text
You can declare multiple managers. Multiple providers is useful if you want to use different storage providers or to isolate your features flags.
# ... twentytwo_labs_feature_flag: managers: manager_foo: factory: twenty-two-labs.feature-flags.factory.array options: features: my_feature_1: enabled: false description: MyFeature1 description text my_feature_2: enabled: true description: MyFeature2 description text my_feature3: enabled: '%env(bool:FEATURE_ENVVAR)%' description: MyFeature3 description text manager_bar: factory: twenty-two-labs.feature-flags.factory.array options: features: my_feature_4: enabled: false description: MyFeature4 description text expression: "is_granted('ROLE_ADMIN')" my_feature_5: [] my_feature_6: ~ my_feature_7: false
When several managers are defined, they are registered in the Symfony dependency injection container as services with the following naming convention: twentytwo_labs_feature_flag.manager.<manager_name>
.
For example, the manager_bar
is accessible with the following service name: twentytwo_labs_feature_flag.manager.manager_bar
.
Manager storage are also registered in the Symfony dependency injection container as services with the following naming convention: twentytwo_labs_feature_flag.storage.<manager_name>
.
Cache
You can cache, PSR6 compatible, all feature flags
twentytwo_labs_feature_flag: cache: enabled: true provider: 'service_name' expires_after: 3600 #default
Use it
As a service
The bundle adds a global ChainedFeatureManager
service you can use in your PHP classes.
use App\Controller; // ... class MyController extends Controller { public function myAction(ChainedFeatureManager $featureManager): Response { if ($featureManager->isEnabled('my_feature_1')) { // my_feature_1 is enabled } if ($featureManager->isDisabled('my_feature_2')) { // my_feature_2 is not enabled } // ... } }
In your Twig templates
You can also check a flag in your templates:
{% if isFeatureEnabled('my_feature_1') %} {% include 'feature1_template.html.twig' %} {% endif %} {% if isFeatureDisabled('my_feature_2') %} {% include 'feature2_template.html.twig' %} {% endif %}
In the routing configuration
The package allows you to restrict a controller access by adding some configuration in your routing definition.
# app/config/routing.yml my_first_route: path: /my/first/route defaults: _controller: AppBundle:Default:index _features: - { feature: my_feature_key, enabled: false } # The action is accessible if "my_feature_key" is disabled my_second_route: path: /my/second-route defaults: _controller: AppBundle:Default:second _features: - { feature: foo } # The action is accessible if "foo" is enabled ... - { feature: bar, enabled: true } # ... and "bar" feature is also enabled
As a controller attribute
You can also restrict a controller access with attributes :
#[Feature(name: "foo", enabled: true)] class MyController extends Controller { #[Feature(name: "foo")] public function annotationFooEnabledAction(): Response { return new Response('MyController::annotationFooEnabledAction'); } #[Feature(name: "foo", enabled: true)] public function annotationFooEnabledBisAction(): Response { return new Response('MyController::annotationFooEnabledAction'); } #[Feature(name: "foo", enabled: false)] public function annotationFooDisabledAction(): Response { return new Response('MyController::annotationFooDisabledAction'); } }
Implement your own storage provider
- First your need to create your storage provider class which implement the
TwentytwoLabs\FeatureFlagBundle\Storage\StorageInterface
interface - After your need to create a factory class which implement the
TwentytwoLabs\FeatureFlagBundle\Factory\StorageFactoryInterface
interface and create your custom storage - Register it in the Symfony dependency injection container
- Specify the storage you want to use in a manager configuration
twentytwo_labs_feature_flag: manager: manager_name: storage: your.custom.service.name options: # arguments need to create the storage service
License
This library is published under MIT license