Feature Flags plugin screenshot
Dark mode ready
Multilingual support
Supports v5.x

Feature Flags

Filament implementation of feature flags and segmentation with Laravel Pennant.

Tags: Forms Form Field Tables Table Column Action
Supported versions:
4.x 3.x
Stephen Jude avatar Author: Stephen Jude

Documentation

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

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

#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.