Globally Eager Loading on Auth::user() to prevent n+1 problem

Posted 8 months ago by rema96

I am building a subscription based site, I am using cashier and I got everything setup also I have a plans table that represents what I have on Stripe, this is simply because I want to list price plans. Furthermore I have features, features and plans are connected with a pivot table n-m.

The problem I am having I would like to know if user has a certain feature, I get this bases on his subscription and then his plan connected to that subscription.

In users model I made a simple function to test this:

public function features()
        return User::join('subscriptions', '', '=', 'subscriptions.user_id')
            ->join('plans', '', '=', 'subscriptions.stripe_plan')
            ->join('feature_plan', 'feature_plan.plan_id', '=', '')
            ->join('features', '', '=', 'feature_plan.feature_id')
            ->where('', '=', $this->id)

With this I get all the features of that user, I also have my relationships setup in Laravel so this App\User::find(1)->subscription()->plan->features->toArray() also works.

Here is a problem if I call hasFeature() function in a loop or even multiple times on the page I will get the famous n+1 problem.

public function hasFeature($feature_id)
        return $this->features() // This will call the function above
                    ->where('slug', '=', $feature_id)

I know the way to solve this is with eager loading but how can I globally eager load this information to my user?

One idea I had was retrieve all the features in User model constructor and assign it to a variable in the class, but I am not really sure if that will work.

Also is there a way to optimize this even more, like cache it so it doesn't make a request every single page load?

Please sign in or create an account to participate in this conversation.

Reply to

Use Markdown with GitHub-flavored code blocks.