Laravel 急切加载多个模型,它们都在同一个表中

Posted

技术标签:

【中文标题】Laravel 急切加载多个模型,它们都在同一个表中【英文标题】:Laravel eagerly loading multiple models that are all in the same table 【发布时间】:2022-01-15 11:06:31 【问题描述】:

举个例子假设我们有一个 users 表和一个 posts 表。

Users 表有 idname 列。

Posts 表具有 creator_idapproved_by_id,它们都存在于 users 表中(引用)。 如何通过一个查询急切地加载它?

select * from posts where id in (z)
select * from users where id in (x,y) //(creator, approver)

目前我有这些关系:

public function created_by()

    return $this->belongsTo(User::class, 'creator_id');


public function approved_by()

    return $this->belongsTo(User::class, 'approved_by_id');

【问题讨论】:

急切加载从不使用单个查询。一个用于获取模型,一个用于每个关系。 如果我选择多行,它使用 where id in (1,2,3,4) = 一个查询。我无法通过同一张表中的多个关系来实现它? 如果您执行Post::with(['created_by', 'approved_by'])->get();,它将执行select * from posts,后跟select * from users where id in (xx)select * from users where id in (yy),其中xx 和yy 是所有原始记录的creator_idapproved_by_id 列的值.这些列都已编入索引,因此不必担心性能问题。 性能不是问题。我只是不喜欢看到运行相同的查询(例如,如果创建者和批准者相同)。 你看不到它,除非你坐在那里监视你的数据库查询日志。 【参考方案1】:

如果我正确理解了问题

User::with(['created_by', 'approved_by'])
   ->get()

【讨论】:

这会创建两个(额外的)查询。 那么只有左连接的任意查询 那是什么?你能举个例子吗? SELEC u.*, s.name FROM users as u LEFT JOIN users as c ON u.creator_id = s.id【参考方案2】:

我保证您没有运行足够大的数据集,因此急切加载的性能不会成为问题。但是,如果有多个查询让您感到困扰,并且您宁愿承担管理查询构建器命令的技术债务,我认为这应该可行:

$post = Post::select('posts.*')
    ->selectRaw('creator.name as creator_name')
    ->selectRaw('approver.name as approver_name')
    ->leftJoin('users as creator', 'posts.creator_id', 'creator.id')
    ->leftJoin('users as approver', 'posts.approved_by_id', 'approver.id')
    ->where('posts.id', $post_id)
    ->get();

我们只是用不同的别名加入用户表两次;为了避免覆盖列值,它们也需要别名。当然,您的数据将采用不同的格式,您将无法访问 $post->created_by->name 之类的内容,而是依赖列别名。

等效的 SQL 查询是:

SELECT posts.*, creator.name AS creator_name, approver.name AS approver_name
FROM posts
LEFT JOIN users AS creator ON (posts.creator_id = creator.id)
LEFT JOIN users AS approver ON (posts.approved_by_id = approver.id)
WHERE posts.id = ?

【讨论】:

以上是关于Laravel 急切加载多个模型,它们都在同一个表中的主要内容,如果未能解决你的问题,请参考以下文章

在laravel [实现过滤器]中将多个表与雄辩和急切的加载一起加入

Laravel 自定义数据透视表关系和急切加载?

使用 Laravel 将两个模型合并到一个分页查询中,并带有急切加载的关系

laravel eloquent - 在嵌套急切加载的关系上不使用

Laravel with() 急切加载返回空数据

Laravel 急切加载限制