Preventing Lazy Loading

Preventing Lazy Loading During Development

Measuring finds N+1 afterward; Model::preventLazyLoading() stops it at the line that causes it. Put Model::preventLazyLoading(! $this->app->isProduction()); in AppServiceProvider::boot() so development and tests throw while production keeps working:

The violation, and the single-model exemptionSQL
use App\Models\Order;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\LazyLoadingViolationException;
Model::preventLazyLoading();
echo 'one model: ', Order::find(3)->customer->name, "\n";
try {
    Order::limit(3)->get()->each(fn ($order) => $order->customer->name);
} catch (LazyLoadingViolationException $e) {
    echo $e::class, "\n", $e->getMessage(), "\n";
}
Output
one model: Chen Wei
Illuminate\Database\LazyLoadingViolationException
Attempted to lazy load [customer] on model [App\Models\Order] but lazy loading is disabled.

find() did not throw: the builder arms the check only when a query returns more than one row. Automatic eager loading runs before the check, so the two combine safely. To log instead of throwing, register Model::handleLazyLoadingViolationUsing(fn ($model, $relation) => Log::warning(...)); here it wrote one warning per order and the queries still ran. Model::shouldBeStrict() adds preventSilentlyDiscardingAttributes() and preventAccessingMissingAttributes() to the check.