Skip to content

evertharmeling/toggler

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Toggler

Build Status

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.

Table of Contents

Requirements

Toggler requires PHP 5.4+

Installation

Composer

$ composer require pierredup/toggler:~1.0

Usage

Config

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');

Using YAML files

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');

Toggle a feature

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 */
}

Toggle a feature based on context

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]);

Using Symfony Expression Language

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

Custom storage to retrieve feature settings

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));

Twig Integration

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' }}

Symfony Integration

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.

Testing

To run the unit tests, execute the following command

$ vendor/bin/phpunit

Contributing

See CONTRIBUTING

License

Toggler is open-sourced software licensed under the MIT license

Please see the LICENSE file for the full license.

About

Feature toggle library for PHP

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • PHP 100.0%