trompette/feature-toggles

Feature toggle infrastructure enabling continuous deployment

5.1.0 2024-03-25 20:24 UTC

This package is auto-updated.

Last update: 2024-04-25 21:45:12 UTC


README

License Stable Version Automated Tests Static Analysis

trompette/feature-toggles

This PHP library implements a feature toggle infrastructure.

Using trompette/feature-toggles library can help a team to deliver new features to users iteratively and safely, in other words: it enables continuous deployment.

For more information on the topic, see Feature Toggles (aka Feature Flags) on MartinFowler.com.

Installation

The trompette/feature-toggles library is distributed on Packagist.

It can be added as a project dependency with the following command:

composer require trompette/feature-toggles

Standalone usage

When working on a new version of a page, deploying gradually the new version can bring a lot of confidence to a team.

But it also brings more work, as the team needs to:

  • keep the code implementing the current version,
  • add the code implementing the new version,
  • and consistently enable the new version for some users.

With trompette/feature-toggles library, enabling the new version is done by asking the toggle router if the current user has a feature:

if ($toggleRouter->hasFeature($currentUser, 'new_page_version')) {
    $templating->render('new_page.tpl', $newParameters);
} else {
    $templating->render('page.tpl', $parameters);
}

Feature registry

Before using the toggle router, new_page_version feature has to be registered:

use Trompette\FeatureToggles\FeatureDefinition;
use Trompette\FeatureToggles\FeatureRegistry;

$featureRegistry = new FeatureRegistry();
$featureRegistry->register(new FeatureDefinition(
    $name = 'new_page_version',
    $description = 'awesome new version of a page',
    $strategy = 'whitelist'
));

Toggling strategies

When defining a feature, a toggling strategy has to be referenced to specify the algorithm deciding if a target has a feature.

Implemented strategies are:

  • feature is enabled for all targets or disabled for all targets, see OnOff class,
  • feature is enabled for whitelisted targets only, see Whitelist class,
  • feature is enabled for a percentage of all targets, see Percentage class.

And strategies can be combined with boolean operators, like so: onoff and whitelist, onoff or whitelist or percentage, etc.

Toggle router

Now that the feature registry is configured, the toggle router can be created:

use Doctrine\DBAL\Connection;
use Trompette\FeatureToggles\DBAL\WhitelistStrategyConfigurationRepository;
use Trompette\FeatureToggles\ToggleRouter;
use Trompette\FeatureToggles\WhitelistStrategy\Whitelist;

$connection = new Connection(...);
$repository = new WhitelistStrategyConfigurationRepository($connection);
$whitelist = new Whitelist($repository);

$toggleRouter = new ToggleRouter(
    $featureRegistry,
    $strategies = ['whitelist' => $whitelist]
);

Strategies are injected as an array indexed with names: these are the references that should be used when registering features.

Feature configuration

The toggle router can be used to configure a feature for a given strategy:

$toggleRouter->configureFeature('feature', 'onoff', 'on');
$toggleRouter->configureFeature('feature', 'onoff', 'off');

$toggleRouter->configureFeature('feature', 'whitelist', 'allow', 'target');
$toggleRouter->configureFeature('feature', 'whitelist', 'disallow', 'target');

$toggleRouter->configureFeature('feature', 'percentage', 'slide', 25);
$toggleRouter->configureFeature('feature', 'percentage', 'slide', 50);

Configuration changes are persisted by calling the associated method on the strategy instance.

All Doctrine DBAL configuration repositories can migrate a schema, since they all implement the SchemaMigrator interface:

use Doctrine\DBAL\Connection;
use Trompette\FeatureToggles\DBAL\WhitelistStrategyConfigurationRepository;

$connection = new Connection(...);
$repository = new WhitelistStrategyConfigurationRepository($connection);
$repository->migrateSchema();

Usage with Symfony

All previous code is optional when using Symfony: everything is glued together by the FeatureTogglesBundle class.

Registering the bundle in config/bundles.php is needed to benefit from the Symfony integration:

return [
    // ...
    Trompette\FeatureToggles\Bundle\FeatureTogglesBundle::class => ['all' => true],
];

Bundle configuration

The bundle can be configured as described by config:dump-reference:

# Default configuration for extension with alias: "feature_toggles"
feature_toggles:
    doctrine_dbal_connection: doctrine.dbal.default_connection
    declared_features:

        # Prototype
        name:
            description:          ~ # Required
            strategy:             ~ # Required

For technical details, see FeatureTogglesConfiguration class.

Container services

There is only one service declared as public: the toggle router with Trompette\FeatureToggles\ToggleRouter or Trompette\FeatureToggles\ToggleRouterInterface as identifier.

There are also useful console commands defined as services and tagged with console.command:

 feature-toggles
  feature-toggles:configure-feature           Configures a feature
  feature-toggles:migrate-dbal-schema         Migrates DBAL schema
  feature-toggles:show-feature-configuration  Shows a feature configuration

More information about the commands can be found in their help messages.

For technical details, see FeatureTogglesExtension class.

License

The trompette/feature-toggles library is released under the MIT License.

See the LICENSE file for more details.

Acknowledgments

The trompette/feature-toggles library is inspired by a practice and a tool used by the Food Assembly development team.

The team discovered the practice with the article Web Experimentation with New Visitors on Etsy's Engineering Blog.