Toggler is a feature toggle library for PHP. It allows you to enable or disable features based on a toggle switch. This is useful in a continues deployment environment, where you can deploy not-yet-ready features which are disabled, and just enable them when the feature is complete.
Toggler requires PHP 5.4+
$ composer require pierredup/toggler:~1.0
To configure Toggler, you need to set the feature flags with a truthy value if it should be enabled.
To enable a feature, any of the following truthy values are accepted:
- (boolean) true
- (int) 1
- '1'
- 'on'
- 'true'
The config needs to be an array with the name of the feature as the key, and a truthy value, callback or expression as the value.
$features = [
'foo' => true,
'bar' => false
];
toggleConfig($features);
You can also pass through a path to a PHP file which should return an array with the config:
// config.php
return [
'foo' => true,
'bar' => false
];
toggleConfig('/path/to/config.php');
In order to use yml files for config, you need to include the Symfony Yaml Component
To install and use the Yaml component, run the following command from the root of your project:
$ composer require symfony/yaml
Then you can define your config using a yaml file
// config.yml
foo: true
bar: false
Pass the path to the yml file to your config
toggleConfig('/path/to/config.yml');
To toggle a feature, use the toggle
function, which takes the feature name as the first argument, and a callback as the second argument.
An optional third callback argument can be passed which whill be called if the
toggle(
'foobar',
function () {
/* will be executed when feature 'foobar' is enabled */
}
);
An optional third callback argument can be passed which will be called if the feature is not enabled
toggle(
'foobar',
function () {
/* will be executed when feature 'foobar' is enabled */
},
function () {
/* will be executed when feature 'foobar' is disabled */
}
);
You can also use the toggle
function as a conditional
if (toggle('foobar')) {
/* will be executed when feature 'foobar' is enabled */
}
To enable a feature only under specific conditions (E.G only enable it for users in a certain group, or only enable it for 10% of visitor etc)
Each feature in the config can take a callback, where you can return a truthy value based on any logic you want to add:
$features = [
'foo' => function (User $user) {
return in_array('admin', $user->getGroups()); // Only enable features for users in the 'admin' group
},
'bar' => function () {
return (crc32($_SERVER['REMOTE_ADDR']) % 100) < 25 // Only enable this features for about 25% of visitors
}
];
Callbacks that takes any arguments, should be called with the context:
$user = User::find(); // Get the current logged-in user
if (toggle('foo', [$user])) {
}
or if you want to use callback functions, the context can always be sent as the last parameter:
$user = User::find(); // Get the current logged-in user
toggle('foo', function () { /* enable feature */ }, [$user]);
You can use the Symfony Expression Language Component to create expressions for your features.
To install and use the Expression Language component, run the following command from the root of your project:
$ composer require symfony/expression-language
Then you can create an expression for your feature:
use Symfony\Component\ExpressionLanguage\Expression;
$feaures = [
'foo' => new Expression('valueOne > 10 and valueTwo < 10')
];
When checking the feature, you need to pass the context to use in your expression:
toggle('foo', ['valueOne' => 25, 'valueTwo' => 5]); // Will return true
If you want to store your config in a different place than an array or config file (E.G MySQL database or redis etc) then you can create a storage class that implements Toggle\Storage\StorageInterface
which can be used to retrieve your config
use Toggle\Storage\StorageInterface;
class RedisStorage implements StorageInterface
{
private $redis;
public function __construct(\Redis $redis)
{
$this->redis = $redis;
}
public function get($key) // This method comes from StorageInterface and needs to be implemented with your custom logic to retrieve values
{
return $this->redis->get($key);
}
}
Then you can pass an instance of your class to the toggleConfig
function
$redis = ...; // Get your redis instance
toggleConfig(new RedisStorage($redis));
Toggler comes with an optional Twig extension, which allows you to toggle elements from Twig templates.
To use the extension, register it with Twig
use Toggler\Twig\Extension\ToggleExtension;
$twig = new Twig_Environment($loader);
$twig->addExtension(new ToggleExtension());
or if you use symfony, register it as a service Note: When using the Symfony bundle, the twig extension is automatically registered.
toggle.twig.extension:
class: Toggler\Twig\Extension\ToggleExtension
tags:
- { name: twig.extension }
Then you can use the toggle
tag in twig templates:
{% toggle 'foo' %}
Some content that will only display if foo is enabled
{% endtoggle %}
To add an alternaltive if a feature is not available, use the else
tag
{% toggle 'foo' %}
Some content that will only display if foo is enabled
{% else %}
Some content that will only display if foo is not enabled
{% endtoggle %}
To use context values with the tag, you can pass it using the with
keyword:
{% toggle 'foo' with [{"valueOne" : 12}] %}
Some content that will only display if foo is enabled based on the context provided
{% endtoggle %}
You can also use the toggle()
function for conditions
{{ toggle('foo') ? 'Foo is enabled' : 'Foo is NOT enabled' }}
Toggler comes with basic integration with the Symfony framework. To enable toggler inside symfony, register the bundle
// AppKernel.php
$bundles = array(
...
new Toggler\Symfony\TogglerBundle(),
...
);
Then inside your app/config/config.yml
or app/config/config_dev.yml
, you can enable features using the following config
toggler:
config:
foo: true
bar: false
If you want to use an expression for a feature config, you can use the @=
syntax:
toggler:
config:
foo: @=myValue > 10
If you want to use a storage class, you can use the service id as the argument for the config:
services:
my.toggler.service:
class: My\Bundle\DbStorage
arguments: [@doctrine]
toggler:
config: my.toggler.service
Note: When using the Symfony bundle, the twig extension is automatically registered.
To run the unit tests, execute the following command
$ vendor/bin/phpunit
See CONTRIBUTING
Toggler is open-sourced software licensed under the MIT license
Please see the LICENSE file for the full license.