Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

brjohnson4's avatar

User and Team Plans at the Same Time

If I have a Spark app where I would like to have the option for individual or team plans offered at the same time, with the same benefits, would I be able to use just the 'subscribed' middleware for views behind the paywall? Or does the 'teamSubscribed' middleware also have to be used for those users who are accessing the site via a team subscription?

Thanks!

0 likes
3 replies
brjohnson4's avatar

Or more specifically, this is my routes file:

// Public Pages
Route::group(['middleware' => 'web'], function () {
    ...
});

// User Pages
Route::group(['middleware' => 'subscribed'], function() {
    ...
]);

But this will not give those who are subscribed to a team access to the user pages. And likewise:

// User Pages
Route::group(['middleware' => 'teamSubscribed'], function() {
    ...
]);

This will not give access to individuals who have subscribed on their own to the user pages.

brjohnson4's avatar
brjohnson4
OP
Best Answer
Level 5

Here's what I have done, and I'm pretty sure that it does what I hope it does. I made a new Middleware to check to see if the user is (a) not on a trial, (b) not subscribed as a user, and (c) not on a team that happens to be subscribed.

This might not be the best way to accomplish this with lots of embedded if statements, but here it is:

    public function handle($request, Closure $next)
    {
        if (! $request->user()->onGenericTrial() ) {
            if(! $request->user()->subscribed() ) {
                if(! $request->user()->hasTeams() ) {
                    return $request->ajax() || $request->wantsJson()
                        ? response('Subscription Required.', 402)
                        : redirect('/settings#/subscription');
                } elseif (! $request->user()->currentTeam->subscribed() ) {
                    return $request->ajax() || $request->wantsJson()
                        ? response('Subscription Required.', 402)
                        : redirect('/settings#/subscription');
                }
            }
        }

        return $next($request);
    }
scottybowl's avatar

Thank you for sharing this - exactly what I needed!

Out of interest, how do you handle custom team plans? In this same Middleware I'm detecting which tenancy we're on and switching to that database.

I'm then defining plans via Spark::, e.g:

Spark::freePlan()
->maxTeams($plan->max_teams)
->features($plan->features)
->trialDays($billing_data->trial_length)
->attributes($plan->attributes);

Would be great to hear your approach.

Please or to participate in this conversation.