{"id":20721708,"url":"https://github.com/yannickl88/features-bundle","last_synced_at":"2025-07-20T17:32:46.756Z","repository":{"id":47453039,"uuid":"49430978","full_name":"yannickl88/features-bundle","owner":"yannickl88","description":"Symfony bundle for managing feature tags","archived":false,"fork":false,"pushed_at":"2024-12-10T19:58:17.000Z","size":78,"stargazers_count":19,"open_issues_count":1,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-20T01:09:14.638Z","etag":null,"topics":["feature-flags","php","symfony","symfony-bundle"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yannickl88.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-01-11T14:19:19.000Z","updated_at":"2024-12-10T19:58:21.000Z","dependencies_parsed_at":"2024-11-16T13:23:47.013Z","dependency_job_id":"66711854-facb-4776-a175-8777f2fe9fc0","html_url":"https://github.com/yannickl88/features-bundle","commit_stats":{"total_commits":40,"total_committers":9,"mean_commits":4.444444444444445,"dds":0.65,"last_synced_commit":"db98dde3be5a579bd7fa97a0734f4ca9ad9f1e18"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/yannickl88/features-bundle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannickl88%2Ffeatures-bundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannickl88%2Ffeatures-bundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannickl88%2Ffeatures-bundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannickl88%2Ffeatures-bundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yannickl88","download_url":"https://codeload.github.com/yannickl88/features-bundle/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannickl88%2Ffeatures-bundle/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266165593,"owners_count":23886640,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["feature-flags","php","symfony","symfony-bundle"],"created_at":"2024-11-17T03:29:05.081Z","updated_at":"2025-07-20T17:32:46.733Z","avatar_url":"https://github.com/yannickl88.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# features-bundle\nThis Symfony bundle provides a way of managing features within a project. A common use-case is to have a certain feature only active under certain condition. Examples would be that you want to activate a feature when the use has a certain role, or when you are not in a production environment (think of testing).\n\nWith this bundle you can configure features to be active or inactive. Using resolvers you decide when a feature is active or not.\n\nRequirements:\n- PHP 7.3 or higher\n- Symfony 4.2 or higher\n \nRecommended installation is via composer: `composer require yannickl88/features-bundle`.\n\nAfter that, you need to register the bundle in the kernel of your application:\n\n```php\n\u003c?php\n// app/AppKernel.php\n\nuse Symfony\\Component\\HttpKernel\\Kernel;\nuse Symfony\\Component\\Config\\Loader\\LoaderInterface;\n\nclass AppKernel extends Kernel\n{\n    public function registerBundles()\n    {\n        $bundles = [\n            new Yannickl88\\FeaturesBundle\\FeaturesBundle(),\n            // …\n        ];\n    }\n}\n```\n\n# Usage\nAll configuration is done using services and your application config. For the following example we want to enable a feature when the GET parameter `beta` is set to `on`.\n\nSo configuring your feature in the `config.yml` of your application.\n\n```yml\nfeatures:\n    tags:\n        beta: # our feature tag\n            request: [\"beta\", \"on\"] # 'app.features.request_resolver' will resolve this key\n```\n\nHere we define a feature tag `beta` which will be resolved with the `request` resolver. Now we need to configure the `request` resolver. We do this with the following service definition:\n```yml\nservices:\n    app.features.request_resolver:\n        class: App\\Feature\\RequestResolver\n        arguments:\n            - '@Yannickl88\\FeaturesBundle\\Feature\\Feature'\n        tags:\n            # config-key is set to resolve the configured key: \"request\" with the options \"beta\" and \"on\"\n            - { name: features.resolver, config-key: request }\n```\nHere we create the `app.features.request_resolver` service and tag it with `features.resolver`. This will then be picked up by the bundle and be registered so we can use it in our feature tags. What we also provide is a `config-key` value. This is the key that we defined in the `config.yml` under the `beta` tag. This will glue your config to your resolver.\n\nFinal thing to do is implement the `RequestResolver`:\n```php\nnamespace App\\Feature;\n\nuse Symfony\\Component\\HttpFoundation\\RequestStack;\nuse Yannickl88\\FeaturesBundle\\Feature\\FeatureResolverInterface;\n\nclass RequestResolver implements FeatureResolverInterface\n{\n    private $request_stack;\n    \n    public function __construct(RequestStack $request_stack)\n    {\n        $this-\u003erequest_stack = $request_stack;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function isActive(array $options = []): bool\n    {\n        // Feature is inactive when there is no request\n        if (null === $request = $this-\u003erequest_stack-\u003egetMasterRequest()) {\n            return false;\n        }\n\n        // $options contains [\"beta\", \"on\"] for the 'beta' feature tag\n        list($key, $expected_value) = $options;\n\n        return $request-\u003eget($key) === $expected_value;\n    }\n}\n```\nNow we can start using the feature in our code. So if I want to check for a feature I can inject it as follows:\n```yml\nservices:\n    app.some.service:\n       class: App\\Some\\Service\n       arguments:\n           - '@Yannickl88\\FeaturesBundle\\Feature\\Feature'\n       tags:\n           - { name: features.tag, tag: beta }\n```\nNotice here that we do not inject the feature directly, but tag the service. The bundle will replace the feature for you. So you can use it as follows in your code:\n```php\nnamespace App\\Some;\n\nuse Yannickl88\\FeaturesBundle\\Feature\\Feature;\n\nclass Service\n{\n    private $feature;\n    \n    public function __construct(Feature $feature)\n    {\n        $this-\u003efeature = $feature;\n    }\n\n    public function someMethod(): void\n    {\n        if ($this-\u003efeature-\u003eisActive()) {\n            // do some extra beta logic when this feature is active\n        }\n    }\n}\n```\nSo if I now add `?beta=on` to my URL. The feature will trigger.\n\n__Note:__ If you remove the tag, it will inject a deprecated feature. This deprecated feature will trigger a warning when the `isActive` is used so you will quickly see where unused feature are used.\n\n# Twig\nIf it also possible to check a feature in your twig templates. Simply use the `feature` function to check if a feature is enabled.\n\n```twig \n{% if feature(\"beta\") %}\n    {# do some extra beta logic when this feature is active #}\n{% endif %}\n```\n\n# Advanced Topics\nIt is possible to configure multiple resolvers per feature tag. You can simply keep adding more in the `config.yml`. So in the example we can extend it to:\n```yml\nfeatures:\n    tags:\n        beta:\n            request: [\"beta\", \"on\"]\n            other: ~\n            more: [\"foo\"]\n```\nAll resolvers must now resolve to `true` in order for this feature to be active. This is usefull if you want to check for multiple conditions.\n\nFurthermore, if you want to have multiple resolvers where only one needs to resolve to `true`, you can use the chain resolver. This can be done as follows:\n```yml\nfeatures:\n    tags:\n        beta:\n            chain:\n                request: [\"beta\", \"on\"]\n                other: ~\n                more: [\"foo\"]\n```\nNotice here we have as resolver `chain` and under this we have your config as before.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyannickl88%2Ffeatures-bundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyannickl88%2Ffeatures-bundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyannickl88%2Ffeatures-bundle/lists"}