Adding feature flags to your Laravel project
This post was published 2 years ago. Some of the information might be outdated!
Feature flags allow you to remotely enable and disable features without deploying new code. They can be toggled at an application level and apply to all users or be scoped to a single user.
Adding them to your Laravel application is incredibly simple thanks to my ryangjchandler/laravel-feature-flags
package.
Begin by installing the package with Composer and running the migrations:
composer require ryangjchandler/laravel-feature-flags
php artisan vendor:publish --tag="feature-flags-migrations"
php artisan migrate
This will create a new feature_flags
table in your application's database.
All methods are called through the RyanChandler\LaravelFeatureFlags\Facades\Features
facade. To create your first flag, call Features::add()
.
use RyanChandler\LaravelFeatureFlags\Facades\Features;
Features::add('show-share-buttons');
This will create a global feature flag called show-share-buttons
. To check if this flag is enabled or disabled, you can use the Features::enabled()
and Features::disabled()
methods.
if (Features::enabled('show-share-buttons')) {
// ...
}
It's probably quite common to conditionally render parts of your Blade templates based on a feature flag. The package also provides a Blade directive that simplifies things.
@feature('show-share-buttons')
<a href="https://twitter.com">
Twitter
</a>
@endfeature
Changing the state of a flag
To change the state of a flag, use the Features::enable()
and Features::disable()
methods.
Features::enable('show-share-buttons');
Features::disable('show-share-buttons');
These methods use an updateOrCreate()
call behind the scenes so if the flag doesn't exist, it will be created automatically.
If you simply want to toggle the state of a flag, i.e. via a button click, you can use the Features::toggle()
method instead.
Model flags
All the examples so far have shown you how to handle global flags. There will definitely be cases where you want flags to be scoped to a single model, e.g. a User
or Team
.
To keep the API and method calls consistent, the package takes advantage of named arguments to create a modifiable method signature. This means that all of the method calls mentioned above will still work for models, you just need to provide a named for
argument and model that implements the RyanChandler\LaravelFeatureFlags\Models\Contracts\HasFeatures
interface.
Here's an example of a User
model that is compatible.
use RyanChandler\LaravelFeatureFlags\Models\Contracts\HasFeatures;
class User extends Authenticatable implements HasFeatures
{
// ...
}
This interface defines a few methods that need to be implemented on the class. To save you the hassle of writing them yourself, you can use the RyanChandler\LaravelFeatureFlags\Models\Concerns\WithFeatures
trait to implement the methods for you.
use RyanChandler\LaravelFeatureFlags\Models\Contracts\HasFeatures;
use RyanChandler\LaravelFeatureFlags\Models\Concerns\WithFeatures;
class User extends Authenticatable implements HasFeatures
{
use WithFeatures;
}
You can now call all of the same methods on Features
and provide a named for
argument.
Features::add('show-social-buttons', for: $user)
Features::enable('show-social-buttons', for: $user)
Features::disable('show-social-buttons', for: $user)
Features::toggle('show-social-buttons', for: $user)
Features::enabled('show-social-buttons', for: $user)
Features::disabled('show-social-buttons', for: $user)
Filament integration
If you're using Filament, there is an additional package that provides a simple UI for managing feature flags. You can find out more in the GitHub repository's README file.