6 min read

Beginner's Guide to Laravel Pennant: Feature Flagging Made Easy

Interested in generating passive income? Join our partnership program and receive a commission on each new client referral. Learn more.

Laravel Pennant

Laravel Pennant is a lightweight and straightforward feature flag package that was introduced with Laravel 10 a few months back. Pennant helps developers roll out new application features incrementally and confidently, and A/B test new interface designs, among other benefits.

In this guide, we'll walk you through the installation and configuration of Laravel Pennant and show you how to define features and perform A/B feature testing. We’re also going to explore two real-world use case examples. So, let's dive in!

Installation and Configuration

To install Laravel Pennant, use the Composer package manager:

composer require laravel/pennant

Next, publish the Pennant configuration and migration files:

php artisan vendor:publish --provider="Laravel\Pennant\PennantServiceProvider"

Lastly, run your application’s database migrations to create a features table:

php artisan migrate

After publishing Pennant’s assets, its configuration file will be located at config/pennant.php. This file allows you to specify the default storage mechanism for resolved feature flag values. By default, Pennant uses a database driver for persistent storage.

Defining Features

Features can be defined in a service provider using the Feature facade. You'll need to provide a name for the feature and closure that resolves the feature's initial value. For example, you can define a feature for incrementally rolling out a new API to your application's users:

Feature::define('new-api', fn (User $user) => $user->isEarlyAccessUser());

You can also use class-based features, which don’t need to be registered with a service provider. To create a class-based feature, use the pennant:feature Artisan command:

php artisan pennant:feature NewApi

Checking Features

To determine if a feature is active, use the active method on the Feature facade. Features are checked against the currently authenticated user by default, but you can also check against another user or scope using the for method:

Feature::for($user)->active('new-api');

For class-based features, provide the class name when checking the feature:

Feature::active(NewApi::class);

You can also use the when method to execute a closure if a feature is active and another closure if it's inactive:

Feature::when(NewApi::class, fn () => "New API", fn () => "Legacy API");

Using the HasFeatures Trait

Add the HasFeatures trait to your application's User model (or any other model with features) to perform feature test directly from the model:

 class User extends Authenticatable {
    use HasFeatures;
    // ...
}
 

Now, you can easily check features by invoking the features method on the model:
if ($user->features()->active('new-api')) {
    // ...
}

Blade Directive

Laravel Pennant provides a @feature directive for seamless feature checking in the Laravel Blade template:

@feature('site-redesign')
    <!-- 'site-redesign' is active -->
@else
    <!-- 'site-redesign' is inactive -->
@endfeature

Real-World Use Case 1: A/B Testing for a New Pricing Page

Imagine you have developed a new pricing page and want to A/B test this new feature against the current version to determine its impact on user conversion rates. Laravel Pennant can be used to control which version of the pricing page users see.

First, define a feature flag for the new pricing page in your AppServiceProvider:

use App\Models\User;

...

Feature::define('new-pricing-page', fn (User $user) => rand(0, 1) === 1);

Now, you can use the @feature directive in your blade template Laravel to conditionally show the new pricing page or the legacy one:

@feature('new-pricing-page')
    @include('pricing.new')
@else
    @include('pricing.legacy')
@endfeature

With this setup, you can collect data on user engagement and conversion rates for each version of the pricing page to determine the most effective design.

Real-World Use Case 2: Incrementally Rolling Out a New Commenting System

Suppose you have developed a new commenting system for your application and want to roll it out incrementally to your users to ensure its stability and performance. You can use Laravel Pennant to control the visibility of the new commenting system.

First, define a feature flag for the new commenting system in your AppServiceProvider:

use App\Models\User;

...

Feature::define('new-commenting-system', fn (User $user) => $user->created_at->diffInDays(now()) < 30);

In this example, users who have signed up within the last 30 days will be able to access the new commenting system.

Now, in your Blade template, use the @feature directive to conditionally display the new commenting system or the legacy one:

@feature('new-commenting-system')
    @include('comments.new')
@else
    @include('comments.legacy')
@endfeature

By rolling out the new commenting system incrementally, you can address any issues that arise and ensure a smooth transition for all users.

Conclusion

Laravel Pennant

In conclusion, Laravel Pennant offers a powerful and flexible way to manage and perform feature flag testing in your Laravel applications. By its simple installation, configuration, and feature definition process, developers can incrementally roll out new features, perform A/B testing, and fine-tune user experiences easily. 

The HasFeatures trait and Blade directives further simplify the feature-checking process, making Pennant an essential tool in any Laravel developer’s toolset. As you begin exploring Laravel Pennant, remember to experiment with real-world use cases to uncover its potential and improve your application’s overall functionality and user experience.

Meet the authors

We are a 200+ people agency and provide product design, software development, and creative growth marketing services to companies ranging from fresh startups to established enterprises. Our work has earned us 100+ international awards, partnerships with Laravel, Vue, Meta, and Google, and the title of Georgia’s agency of the year in 2019 and 2021.

Contact us