Laravel 8 新增功能之如何验证N+1查询

Laravel框架
459
0
0
2022-04-19

PR 地址:github.com/laravel/framework/pull/...

Laravel 的 Eloquent ORM 是非常方便和强大的,只要在模型层做好相关配置和关联,就可以非常方便的进行查询。

但是,这无意也会给程序性能带来隐患,比如查询 N+1的问题。

举个栗子:

用户可以发表多篇博文,那么 UserModel 和 PostModel 的关系就是 1对多的关系。

// User Model
public function posts()
{
    return $this->hasMany(Post::class);
}

// UserController
// 查询一个用户
$users = User::get();
// 查询该用户的所有博文
foreach($users as $user) {
    $user->posts;
}

上面的代码就存在N+1查询的问题,应该尽量避免这种问题。如果发现呢?现在可以在 AppServiceProvider 中进行如下设置:

// User Model
public function boot()
{
    Model::preventLazyLoading(! app()->isProduction());
}

这样在有 N+1 风险的时候,就会抛出 Illuminate\Database\LazyLoadingViolationException 异常,然后再根据异常信息去解决就可以了,例如使用:

$users = User::with('posts')->get();

foreach($users as $user) {
    $user->posts;
}

with 是为了解决 N+1 而生的。