Filament Feature Flags
Filament implementation of feature flags and segmentation with Laravel Pennant.
#Filament Feature Flags
Filament implementation of feature flags and segmentation with Laravel Pennant.
- Apply features for a segment of users (i.e., by country or currency)
- Apply features for individual users (i.e., by email or ID)
- Apply features for all users
- Create custom feature segmentation
- Feature event handling (i.e., run code when a feature is activated/deactivated)
- UI to modify a segment of users
- Purge all resolved features from storage
#Learn More
#Installation
You can install the package via composer and publish and run the migrations with:
composer require stephenjude/filament-feature-flags php artisan vendor:publish --provider="Laravel\Pennant\PennantServiceProvider" php artisan vendor:publish --provider="Stephenjude\FilamentFeatureFlag\FeatureFlagPluginServiceProvider" php artisan migrate
#Usage
This package is exclusively for class based features.
You'll have to register the plugin in your panel provider.
public function panel(Panel $panel): Panel { return $panel ->plugins([ \Stephenjude\FilamentFeatureFlag\FeatureFlagPlugin::make() ]); }
You don't have to call
Feature::discover()in your service provider boot method, this package already did that for you.
#Authorization/Access Control
You can authorize the plugin for users with a specific role/permission:
FeatureFlagPlugin::make() ->authorize(fn() => auth()->user()->can('view.features'));
#Create Class Based Feature
To create a class based feature, you may invoke the pennant:feature Artisan command.
php artisan pennant:feature WalletFunding
When writing a feature class, you only need to use the Stephenjude\FilamentFeatureFlag\Traits\WithFeatureResolver
trait, which will be invoked to resolve the feature's initial value for a given scope.
<?php namespace App\Features; use Stephenjude\FilamentFeatureFlag\Traits\WithFeatureResolver; class WalletFunding { use WithFeatureResolver; }
#Overriding Default Values per Feature
If you need more control over the default value of a feature, you can either add a defaultValue property.
<?php namespace App\Features; use Stephenjude\FilamentFeatureFlag\Traits\WithFeatureResolver; class WalletFunding { use WithFeatureResolver; protected bool $defaultValue = false; }
Or a defineValue method.
<?php namespace App\Features; use Stephenjude\FilamentFeatureFlag\Traits\WithFeatureResolver; class WalletFunding { use WithFeatureResolver; protected function defaultValue(mixed $scope): bool { return false; } }
The result of these methods will get cast to a boolean.
If neither are defined, the default value gets fetched from the filament-feature-flags.default config entry.
#Feature Segmentation
By default, this package resolves scope using the App\Models\User model and the default segment applies features for individual or group of users by email.
To add a new segment, add this code snippet below to the segments section on the filament-feature-flag config:
#Example 1: Adding Segment For Currency
[
'column' => 'currency',
'source' => [
'model' => \App\Models\Currency::class,
'value' => 'code',
'key' => 'code',
],
],
#Example 2: Adding Segment For Country
[
'column' => 'country',
'source' => [
'model' => \App\Models\Country::class,
'value' => 'name',
'key' => 'name',
],
],
#Feature Events
When a feature is activated or deactivate, this package dispatches events which your application can subscribe to. You can listen to these events inside your EventServiceProvider class.
use Stephenjude\FilamentFeatureFlag\Events\{FeatureActivatedForAll,FeatureDeactivatedForAll,FeatureSegmentCreated,FeatureSegmentModified,FeatureSegmentRemoved,RemovingFeatureSegment}; protected $listen = [ FeatureActivatedForAll::class => [ // Dispatched after feature is activated for all users. ], FeatureDeactivatedForAll::class => [ // Dispatched after feature is deactivated for all users. ], FeatureSegmentCreated::class => [ // Dispatched after feature segment is created. ], FeatureSegmentModified::class => [ // Dispatched after feature segment is modified. ], RemovingFeatureSegment::class => [ // Dispatched before feature segment is removed. ], FeatureSegmentRemoved::class => [ // Dispatched after feature segment is removed. ], ];
This is the contents of the published config file:
return [ // This package supports only class based features. /* * This is the default state for all class based features and * state will be used if there is no segmentation. */ 'default' => true, /* * Default scope: User::class, Team::class */ 'scope' => App\Models\User::class, /* * Column names and data source that can be used to activate or deactivate for a segment of users. * This columns must exist on the users table and the data source must be a model. * COLUMN: The column name as defined on the default scope model config. * MODEL: The eloquent model of the source table. * VALUE: The column to be used as value. * KEY: The column to be used as key. */ 'segments' => [ [ 'column' => 'email', 'source' => [ 'model' => App\Models\User::class, 'value' => 'email', 'key' => 'email', ], ], ], 'panel' => [ /* * Navigation group for admin panel resource. */ 'group' => 'Settings', /* * Navigation item label for admin panel resource. */ 'label' => 'Manage Features', /* * Resource title for admin panel resource. */ 'title' => 'Manage Features & Segments', /* * Navigation item icon for admin panel resource. */ 'icon' => 'heroicon-o-cursor-arrow-ripple' ] ];
#Localization
The package supports i18n. Publish the translation files to customize or add new locales:
php artisan vendor:publish --tag=filament-feature-flags-translations
Then create lang/vendor/filament-feature-flags/{locale}/messages.php for your language.
#Screenshots:
#Testing
composer test
#Changelog
Please see CHANGELOG for more information on what has changed recently.
#Contributing
Please see CONTRIBUTING for details.
#Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
#Credits
#License
The MIT License (MIT). Please see License File for more information.