phputil / flags
A lightweight, extensible feature flags framework for PHP
Requires
- php: ^7.4 || ^8.0
Requires (Dev)
- captainhook/captainhook: ^5.18
- friendsofphp/php-cs-fixer: ^3.35
- kahlan/kahlan: ^5.2
- phpstan/phpstan: ^1.10
- phputil/restage: ^0.3.0
README
🚩 A lightweight, customizable feature flags framework for PHP
You can customize:
- 🧠 How flags are evaluated, through Strategies.
- 💾 How flags are stored, through Storages.
- 📢 Who is notified about flag changes or removal, through Listeners.
Installation
PHP 7.4 or later. No external dependencies.
composer require phputil/flags
👉 You may also like to install some of the official extensions.
Extensions
Official extensions:
phputil/flags-pdo
- a PDO-based storage.- ⏳ SOON -
phputil/flags-firebase
- a Firebase-based storage. phputil/flags-webhooks
a listener that works like a webhook, by notifying external APIs about flags' changes.
Third-party extensions:
- Create yours and open an Issue to be evaluated. It may appear here.
Usage
Basic flag checking:
require_once 'vendor/autoload.php'; use phputil\flags\FlagManager; // By default, it uses a storage-based strategy with an in-memory storage $flag = new FlagManager(); if ( $flag->isEnabled( 'my-cool-feature' ) ) { echo 'Cool feature available!', PHP_EOL; } else { echo 'Not-so-cool feature here', PHP_EOL; }
Customizing a certain verification:
// ... use phputil\flags\FlagVerificationStrategy; $flag = new FlagManager(); $myLuckBasedStrategy = new class implements FlagVerificationStrategy { function isEnabled( string $flag ): bool { return rand( 1, 100 ) >= 50; // 50% chance } }; if ( $flag->isEnabled( 'my-cool-feature', [ $myLuckBasedStrategy ] ) ) { echo 'Cool feature available!', PHP_EOL; } else { echo 'Not-so-cool feature here', PHP_EOL; }
Customizing all the verifications:
$flag = new FlagManager( null, [ $myLuckBasedStrategy ] ); if ( $flag->isEnabled( 'my-cool-feature' ) ) { ...
Setting a flag:
$flag->enable( 'my-cool-feature' ); $flag->disable( 'my-cool-feature' ); $flag->setEnable( 'my-cool-feature', true /* or false */ );
Removing a flag:
$flag->remove( 'my-cool-feature' );
Retrieving flag data:
$flagData = $flag->getStorage()->get( 'my-cool-feature' ); // null if not found
Adding a listener:
// ... use phputil\flags\FlagListener; use phputil\flags\FlagData; $myListener = new class implements FlagListener { public function notify( string $event, FlagData $flagData ): void { if ( $event === 'change' ) { echo 'Flag ', $flagData->key, ' is now ', $flagData->enabled ? 'enabled': 'disabled', PHP_EOL; } else if ( $event === 'removal' ) { echo 'Flag ', $flagData->key, ' was removed.', PHP_EOL; } } }; $flag->addListener( $myListener ); // v0.5.0+ // or $flag->getListeners()->add( $myListener ); $flag->enable( 'my-cool-feature' ); // Notify the listener
Customization
Storages
Use a different flag storage by:
- Creating your own, extending
FlagStorage
; OR - Using an external storage extension.
How to configure it:
$storage = /* Create your storage here, e.g. new InMemoryStorage() */; $flag = new FlagManager( $storage );
Storages available in the framework:
InMemoryStorage
, that store flags in memory.
Strategies
Use a flag verification strategy by:
- Creating your own, extending
FlagVerificationStrategy
; OR - Using an external strategy extension.
How to configure it globally:
$strategies = [ /* pass your strategies here */ ]; $flag = new FlagManager( null, $strategies );
Strategies available in the framework:
StorageBasedVerificationStrategy
, that checks flags in a storage.EnvBasedVerificationStrategy
, that checks flags based on environment variables.
👉 A flag is considered enabled when all the strategies considered it enabled.
Listeners
Define a listener by:
- Creating your own, extending
FlagListener
; OR - Using an external listener extension.
How to configure it:
$flag->addListener( $myListener ); // v0.5.0+ // or $flag->getListeners()->add( $myListener );
Roadmap
- Extensible library
- Official extensions:
- PDO-based storage
- Firebase-based storage
- Webhook-like listener
- REST API (external repository)
- Web-based control panel (external repository)