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

StephanGadzhev's avatar

Laravel Limit user by subscription plan

Hi there, I am building subscription plan application in Laravel. I was wondering which is the best practice to place the code for the logic. The idea is to limit the creation of models by plan. Lets say the silver plan - 10 locations and 50 personnel, gold plan - 20 locations 100 personnel and so on. I deceided to implement the "count and check" logic but still not sure if its the best place to implement the logic into the Model or create a Policy or even some kind of Service class to handle the code.

0 likes
7 replies
ederson's avatar

I used policies although i was tempted to add the logic in the model. I didn't have very complicated rules but still it is much cleaner this way

1 like
martinbean's avatar
Level 80

@stephanegadzhev A policy is probably the best place, given you have the authenticated user instance (the user trying to create the resource) and the resource type to hand:

use App\Models\User;
use Illuminate\Auth\Access\Response;

class LocationPolicy
{
    public function create(User $user)
    {
        $count = $user->locations()->count();

        $limit = match ($user->plan_id) {
            'plan-silver' => 10,
            'plan-gold' => 20,
        };

        return ($count < $limit)
            ? Response::allow()
            : Response::deny('You have exceeded your plan limit.');
    }
}

You can now just check if a user can create a location, knowing that plan limits will be automatically checked:

public function store(StoreLocationRequest $request)
{
    $this->authorize('create', Location::class);

    $user = $request->user();

    $location = $user->locations()->create($request->validated());

    // TODO: Return response
}

Or, if you’re using resource controllers, then you can just automatically authorise all actions so long as you’re sticking to Laravel’s conventions:

class LocationController extends Controller
{
    public function __construct()
    {
        $this->authorizeResource(Location::class);
    }

    public function create()
    {
        return view('locations.create');
    }

    public function store(StoreLocationRequest $request)
    {
        $user = $request->user();

        $location = $user->locations()->create($request->validated());

        // TODO: Return response...
    }
}
StephanGadzhev's avatar

@martinbean Just did the same with the LocationPolicy, but I like the approach with the match() function so i am going to "steal" it. Thanks ^^

1 like
martinbean's avatar

@StephaneGadzhev Steal away ☺️

I didn’t know how you actually mapped limits to plans, but if it’ll work for your use case then feel free to adopt that approach.

StephanGadzhev's avatar

@martinbean It’s a long and painful road to explain the whole situation, but the approach clicked well with the situation.

1 like
nabilhassen's avatar

I know this is a bit old but let me suggest my Laravel Usage Limiter package for anyone who might need it in the future.

github.com/nabilhassen/laravel-usage-limiter

Please or to participate in this conversation.