导读:本期聚焦于小伙伴创作的《PHP怎么使用Eloquent Relationships预加载实现Laravel N+1查询优化》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《PHP怎么使用Eloquent Relationships预加载实现Laravel N+1查询优化》有用,将其分享出去将是对创作者最好的鼓励。

在Laravel项目中使用Eloquent ORM进行数据操作时,N+1查询问题是影响接口响应速度的常见因素。当我们需要获取主模型集合后,再逐个访问其关联模型时,就会产生大量重复的SQL查询,而Eloquent Relationships提供的预加载功能可以完美解决这个问题。

PHP怎么使用Eloquent Relationships预加载实现Laravel N+1查询优化

N+1查询问题的产生原因

假设我们有两个模型,User模型和Post模型,用户和文章是一对多关系,User模型中定义了关联方法:

<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;

class User extends Model
{
    // 定义用户和文章的关联
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

如果我们要获取所有用户,并且输出每个用户发布的文章标题,常见的错误写法如下:

<?php

$users = User::all();

foreach ($users as $user) {
    // 每次循环都会执行一次查询文章表的SQL
    echo $user->name . "的文章:" . $user->posts->pluck('title')->join(',') . PHP_EOL;
}

这段代码的执行流程是:首先执行1次查询获取所有用户,然后有多少个用户就执行多少次查询获取对应用户的文章,总查询次数是1+N,也就是N+1查询问题。当用户数量较多时,会产生大量数据库查询,严重影响性能。

使用预加载解决N+1查询问题

Eloquent提供了with方法来实现关联预加载,只需要在查询主模型时指定要预加载的关联名称,就可以在1次查询中把主模型和关联模型的数据都加载完成。

基本预加载用法

针对上面的场景,优化后的代码如下:

<?php

// 预加载posts关联,只执行2次SQL查询
$users = User::with('posts')->get();

foreach ($users as $user) {
    // 这里不会再次执行查询,直接使用预加载的数据
    echo $user->name . "的文章:" . $user->posts->pluck('title')->join(',') . PHP_EOL;
}

执行这段代码时,Laravel会先执行1次查询获取所有用户,再执行1次查询获取所有用户关联的文章,总查询次数只有2次,无论用户数量多少都不会增加查询次数,性能提升非常明显。

多关联预加载

如果一个模型有多个关联需要预加载,可以在with方法中传入关联名称数组:

<?php

// 预加载posts和comments两个关联
$users = User::with(['posts', 'comments'])->get();

不同关联类型的预加载方式

Eloquent支持多种关联类型,预加载的使用方式基本一致,只需要指定对应的关联方法名称即可。

一对一关联预加载

假设User模型和Profile模型是一对一关系,User模型中定义关联:

<?php

public function profile()
{
    return $this->hasOne(Profile::class);
}

预加载写法:

<?php

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

多对多关联预加载

假设User模型和Role模型是多对多关系,User模型中定义关联:

<?php

public function roles()
{
    return $this->belongsToMany(Role::class);
}

预加载写法:

<?php

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

预加载的进阶用法

嵌套预加载

如果关联模型还有自己的关联,我们可以使用点号语法实现嵌套预加载。比如Post模型关联了Comment模型,我们要预加载用户的文章以及文章下的评论:

<?php

// 预加载posts关联,同时预加载posts关联的comments
$users = User::with('posts.comments')->get();

条件预加载

如果我们需要在预加载时添加查询条件,可以传入闭包函数对关联查询进行约束:

<?php

// 预加载用户发布的已审核文章
$users = User::with(['posts' => function ($query) {
    $query->where('is_checked', 1);
}])->get();

延迟预加载

如果我们在获取主模型集合之后,才决定要预加载关联,可以使用load方法实现延迟预加载:

<?php

$users = User::all();

// 后续需要用到用户的文章数据,再执行延迟预加载
$users->load('posts');

预加载使用注意事项

  • 预加载的关联名称必须和模型中定义的关联方法名称完全一致,否则会报错。
  • 不要对已经预加载的关联再次调用预加载,避免不必要的查询。
  • 如果关联数据量非常大,预加载可能会导致内存占用过高,这时候需要结合分页查询使用。
  • 使用with预加载时,关联查询的SQL会自动处理关联条件,不需要手动指定外键约束。

通过合理使用Eloquent Relationships预加载功能,我们可以有效解决Laravel开发中的N+1查询问题,减少数据库查询次数,提升应用的整体性能。在实际开发中,建议养成在需要访问关联数据时优先使用预加载的习惯,避免无意义的性能损耗。

PHPEloquent_RelationshipsLaravelN+1查询优化修改时间:2026-07-05 05:33:13

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。