Laravel Pennant - store against session? For A/B testing

114 Views Asked by At

I want to use Laravel Pennant to implement A/B testing within my application.

I was wondering whether it is possible to store the feature against the current user session to show two different layouts for users that are not authenticated.

Is this possible? If so, would anyone be able to provide an example?

2

There are 2 best solutions below

1
Muhammad Ikram UL Mustafa On

To achieve this with unauthenticated users, you can use Laravel's session to store and retrieve the feature flag state for each user.

Here's a simplified example to illustrate how you could implement this:

Middleware for Session-Based Feature Flags: Create a middleware that checks if a feature flag is set in the user's session. If not, it decides which version of the feature to show (e.g., A or B), stores this choice in the session, and then continues with the request.

  1. Implement the Middleware: Generate a new middleware:

    php artisan make:middleware FeatureFlagMiddleware

In the handle method of your new middleware, use the session to store or retrieve the user's feature flag state. Here's an example:

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class FeatureFlagMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        // Check if the feature flag is already determined for the session
        if (!$request->session()->has('feature_flag_A_or_B')) {
            // Determine the feature flag for this session, e.g., randomly or based on any other logic
            $featureFlag = rand(0, 1) ? 'A' : 'B';
            
            // Store the determined feature flag in the session
            $request->session()->put('feature_flag_A_or_B', $featureFlag);
        }

        return $next($request);
    }
}

Don't forget to register your middleware in the kernel or route. Use the Feature Flag in Your Controller or View:

In your controller or directly in your view, use the feature flag from the session to determine which layout or content to display. For example:

$featureFlag = session('feature_flag_A_or_B');
if ($featureFlag == 'A') {
    // Show layout A
} else {
    // Show layout B
}

After that, Register and Apply Your Middleware.

This example is a basic implementation and can be adapted based on your specific needs, such as using more sophisticated logic to assign the feature flag or integrating more directly with Laravel Pennant's features for a more dynamic and configurable approach. Remember, the key here is using the session to persist the user's feature flag state across their interactions with your application without requiring authentication.

4
Flame On

Using a session as a feature flag is pretty straight forward. Just save it to the session in the feature definition, and retrieve it from the session on subsequent calls.

use Illuminate\Http\Request;
use Illuminate\Support\Lottery;
use Laravel\Pennant\Feature;

Feature::define('some-feature-v2', function (string $scope) {
    $session = session();

    if (!is_null($state = $session->get('feature:some-feature-v2'))) {
        return $state;
    }

    $session->put('feature:some-feature-v2', $enabled = Lottery::odds(50 / 100)());

    return $enabled;
});

The $scope argument is set using the Feature::for(...) function, which in this case is the session ID. It is this key that will be saved to the database (or whichever Pennant driver you're using) for quick retrieval of a feature flag.

if (Feature::for(session()->getId())->active('some-feature-v2')) {
    // The feature is enabled.
}

Note that using the session is highly transient since it may expire quite soon depending on your settings. Also the same user will experience different things on different devices.

You also might want to use php artisan pennant:purge or php artisan pennant:purge some-feature-v2 after a while since the records in your database may accumulate quite fast if you save everything by a session ID (every private browser is a new session).