我有Album模型和AlbumItem模型 - 它代表照片。
在相册模型中,我有:
public function first_photo(){
return $this->hasOne('AlbumItem')->orderBy('sort_order', 'asc');
}
在控制器中,我使用第一张照片加载了相册列表:
Album::with(['first_photo'])->get();
它生成如下的SQL查询:
select * from `album_items`
where `album_items`.`album_id` in (1,2,3,4,5) order by `sort_order` asc
但它会返回所有具有album_id = 1,2,3,4,5 ...
的专辑项目
我只需要第一个具有sort_order
最小值的专辑项目,这就是为什么我尝试使用GROUP BY但是然后ORDER BY不起作用...即我想要更改first_photo()
方法所以它会首先是ORDER BY sort_order
,然后是GROUP BY album_id
:
select * from (
select * from `album_items`
where `album_items`.`album_id` in (1,2,3,4,5) order by `sort_order` asc
) temp
group by temp.`album_id`
是否可以使用hasOne
方法获取此内容?
答案 0 :(得分:3)
public function first_photo(){
return $this->hasOne('AlbumItem')->orderBy('sort_order', 'asc')->limit(1);
}
这将只返回一个值。当我们定义关系和急切负载时,它将始终触发两个查询。您也可以在此处按album_id添加分组。
Album::with(['first_photo'=> function($q){
return $q->limit(1)->groupBy('album_id');
}])->get();
答案 1 :(得分:1)
好吧,我决定写一个答案..
对于初学者,你应该避免与非关系事物(sort
,order
,group
,where
等)的混乱。将其更改为:
public function first_photo(){
return $this->hasOne('AlbumItem');
}
这背后的理由是您可以执行类似$model->first_photo()->create([.. relation definition ..])
的操作,或者$albumItem->Album()->associate([$model])
,或者甚至可以明确地将AlbumItem
实例分配给Album
&#39} first_photo
关系。
如果您希望我只需要第一个具有最小sort_order值的相册项目,这就是我尝试使用的原因,您可以尝试:
Album::with(['first_photo' => function($query){
$query->orderBy('sort_order', 'asc')->first();
}])->get();
修改强>:
关于Laravel如何处理with()
查询的一些解释。 Laravel将首先获取指定的Album
,然后继续获取与AlbumItem
相关的所有Album
。映射是在没有连接的情况下完成的,但是由PHP在内存中完成。 documentation中陈述了这一点(内存部分并不十分清楚)。但是,在Laravel的Eloquent Query Builder深处,他们肯定会在PHP中进行关系匹配 - 可以找到here和$relation->match(..)
here,好吧,它是一个摘要,其中一个例子是this。相当深,但你应该挖掘框架的一部分..
此循环将执行1个查询以检索表中的所有书籍,然后执行另一个查询以检索作者。因此,如果我们有25本书,这个循环将运行26个查询:1个用于原始书籍,25个额外查询用于检索每本书的作者。
幸运的是,我们可以使用预先加载将此操作减少到只有2个查询。查询时,您可以使用with方法指定应该急切加载哪些关系: