#database #development #laravel #pattern #php

It's a good practice to disable lazy-loading in your Laravel code when running in development (or testing) mode. This will help you avoid N+1 problems.

You can easily do this by adding the following to your AppServiceProvider::boot function:

 1namespace App\Providers;
 2
 3use Illuminate\Database\Eloquent\Model;
 4use Illuminate\Support\Facades\App;
 5use Illuminate\Support\ServiceProvider;
 6
 7class AppServiceProvider extends ServiceProvider
 8{
 9    public function boot()
10    {
11        Model::preventLazyLoading(App::environment('local', 'testing'));
12    }
13
14    public function register()
15    {
16    }
17}

There's one drawback though, it's all or nothing. When you are working with an existing codebase and you want to gradually fix the issues, you might need to (temporarily) disable the check for certain models and / or relations.

To do so, you can register a closure using Model::handleLazyLoadingViolationUsing to customize the check

 1namespace App\Providers;
 2
 3use App\Domains\User\CompanyUser;
 4use Illuminate\Database\Eloquent\Model;
 5use Illuminate\Database\LazyLoadingViolationException;
 6use Illuminate\Support\ServiceProvider;
 7use Illuminate\Support\Facades\App;
 8
 9class AppServiceProvider extends ServiceProvider
10{
11    public function boot()
12    {
13        Model::handleLazyLoadingViolationUsing(function (Model $model, string $relation): void {
14            if ($model instanceof CompanyUser) {
15                if ($relation === 'offices') {
16                    return;
17                }
18            }
19            throw new LazyLoadingViolationException($model, $relation);
20        });
21
22        Model::preventLazyLoading(App::environment('local', 'testing'));
23    }
24
25    public function register()
26    {
27    }
28}

In the above example, we no longer throw the lazy-loading error when loading the offices relation on the model CompanyUser.