Laravel 急切加载多个模型,它们都在同一个表中
Posted
技术标签:
【中文标题】Laravel 急切加载多个模型,它们都在同一个表中【英文标题】:Laravel eagerly loading multiple models that are all in the same table 【发布时间】:2022-01-15 11:06:31 【问题描述】:举个例子假设我们有一个 users 表和一个 posts 表。
Users 表有 id 和 name 列。
Posts 表具有 creator_id 和 approved_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_id
和approved_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 将两个模型合并到一个分页查询中,并带有急切加载的关系