How to set up feature flags in Laravel

Feb 15, 2024

Feature flags help you conditionally roll out and release features safely. This tutorial shows you how integrate them in Laravel using PostHog.

We'll create a basic Laravel app, add PostHog, create a feature flag, and then implement the flag to control content in our app.

1. Create a basic Laravel app

First, ensure PHP and Composer are installed. Then, create a new Laravel project called laravel-feature-flags:

Terminal
composer create-project laravel/laravel laravel-feature-flags
cd laravel-feature-flags

Next, replace the code in resources/views/welcome.blade.php with a simple heading and paragraph:

resources/views/welcome.blade.php
<!DOCTYPE html>
<html>
<body>
<h1>Laravel feature flags tutorial</h1>
<p>{{ $paragraphText }}</p>
</body>
</html>

Replace the code in routes/web.php with a route to return our view:

routes/web.php
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
$paragraphText = 'Placeholder text';
return view('welcome', ['paragraphText' => $paragraphText]);
});

Run php artisan serve and navigate to http://127.0.0.1:8000 to see our app in action.

Basic Laravel app

2. Add PostHog to your app

With our app set up, it’s time to install and set up PostHog. If you don't have a PostHog instance, you can sign up for free.

To start, run composer require posthog/posthog-php to install PostHog’s PHP SDK.

Next, we initialize PostHog in the boot method of app/Providers/AppServiceProvider.php. Replace the existing code in that file with the following:

app/Providers/AppServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use PostHog\PostHog;
class AppServiceProvider extends ServiceProvider
{
public function boot(): void
{
PostHog::init(
'<ph_project_api_key>',
[
'host' => 'https://us.i.posthog.com'
]
);
}
}

You can find your project API key and instance address in your project settings.

Lastly, we capture a $pageview event with PostHog in our route:

routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use PostHog\PostHog;
Route::get('/', function () {
$paragraphText = 'Placeholder text';
$distinctId = 'placeholder-user-id';
PostHog::capture([
'distinctId' => $distinctId,
'event' => '$pageview'
]);
return view('welcome', ['paragraphText' => $paragraphText]);
});

With this set up, restart your app and then refresh your browser a few times. You should now see the captured event in your PostHog activity tab.

Events captured in PostHog

3. Create a feature flag in PostHog

With PostHog set up, your app is ready for feature flags. To create one, go to the feature flags tab in PostHog and click New feature flag. Enter a flag key (like my-cool-flag), set the release condition to roll out to 100% of users, and press "Save."

Feature flag created in PostHog

You can customize your release conditions with rollout percentages, and user or group properties to fit your needs.

4. Implement the flag code

To implement the feature flag, we:

  1. Fetch the my-cool-flag flag using PostHog::isFeatureEnabled().
  2. Update the paragraph text based on whether the flag is enabled or not.
routes/web.php
// rest of your code
Route::get('/', function () {
$paragraphText = 'Placeholder text';
$distinctId = 'placeholder-user-id';
$isFlagEnabled = PostHog::isFeatureEnabled(
'my-cool-flag',
$distinctId,
);
if ($isFlagEnabled) {
$paragraphText = "Flag enabled!";
} else {
$paragraphText = "Flag disabled!";
}
// rest of your code
});

When you restart your app and refresh the page, you should see the text updated to Flag enabled!.

💡 Setting the correct distinctId:

You may notice that we set $distinctId = 'placeholder-user-id' in our flag call above. In production apps, to ensure you fetch the correct flag value for your user, distinctId should be set to their unique ID.

For logged-in users, you typically use their email or user ID as their distinctId. For logged-out users, assuming they made their request from a browser, you can use values from their request cookies. See an example of this in our Nuxt feature flags tutorial.

5. Include the flag when capturing your event

To ensure any captured events are associated with the correct flag value, we need to include our flag information when capturing them. This enables us to breakdown insights by feature flag value.

To do this for our $pageview event, we add the $feature/my-cool-flag key to our event properties when capturing:

routes/web.php
// rest of your code
Route::get('/', function () {
// rest of your code
PostHog::capture([
'distinctId' => $distinctId,
'event' => '$pageview',
'properties' => [
'$feature/my-cool-flag' => $isFlagEnabled
]
]);
return view('welcome', ['paragraphText' => $paragraphText]);
});

Now when your event is captured, you should see the flag value in the event details in PostHog:

Flag details in event in PostHog

Further reading

Subscribe to our newsletter

Product for Engineers

Sharing what we learn about building successful products. Read by 25,000+ founders and developers.

We'll share your email with Substack

Comments