Php Laravel Eloquent:通过关系表过滤模型
我有Php Laravel Eloquent:通过关系表过滤模型,php,laravel,eloquent,laravel-5,Php,Laravel,Eloquent,Laravel 5,我有位置和位置表格。 这个地方可能有很多地方。位置属于地点 地点: id 标题 地点: id place\u id 楼层 lat lon class Location extends Model { public function place() { return $this->belongsTo('App\Place'); } } 及 我需要找地方,只属于一楼从places.id=locations.place\u id where loca
位置
和位置
表格。
这个地方可能有很多地方。位置属于地点
地点:
id
标题
地点:
id
place\u id
楼层
lat
lon
class Location extends Model {
public function place()
{
return $this->belongsTo('App\Place');
}
}
及
我需要找地方,只属于一楼<代码>从places.id=locations.place\u id where locations.floor=1上的places内部连接位置中选择*
该如何用雄辩的语言表达
类似于
Place::where('locations.floor','=',1)->get()
存在吗
是的,我知道那里有,
:
Place::whereHas('locations', function($q)
{
$q->where('floor', '=', 1);
})->get()
但它会生成一个带有计数的有点复杂的查询:
select * from `places` where (select count(*) from `locations` where `locations`.`place_id` = `places`.`id` and `floor` = '1') >= 1
这不管用吗
class Location extends Model {
public function place()
{
return $this->belongsTo('App\Place');
}
}
$locations = Location::where('floor', '=', 1);
$locations->load('place'); //lazy eager loading to reduce queries number
$locations->each(function($location){
$place = $location->place
//this will run for each found location
});
最后,任何orm都不是用于数据库使用优化的,也不值得期待它产生漂亮的sql 我还没有尝试过这个,但您有急切的加载,您可能有一个条件:
$places = Place::with(['locations' => function($query)
{
$query->where('floor', '=', 1);
}])->get();
试试这个:
Place::join('locations', 'places.id', '=', 'locations.place_id')
->where('locations.floor', 1)
->select('places.*')
->get();
1个位置->1个位置。所以这段代码只为我提供了一个位置,而不是从1楼到$locations,我使用first()只是为了演示$位置->每个(函数($location){$place=$location->place})`是的,我知道我可以循环,但是这个简单的操作有点复杂。但是谢谢你的回答,我想我会用你的方法。。。我的让我困惑=(它通过
whereHas
生成的查询有什么问题?问题是它使用aggregate count()函数进行奇怪的查询。也许,只是也许,在引擎mysql后面,它将此转换为简单连接(或者连接到此,我真的不知道)。它是否等于我提供的联接方法?问题是,对于Laravel,联接直到需要时才会发生。它在每一步都会执行尽可能高效的请求。在这种情况下,由于不需要联接,因此不会执行联接,并且会执行count()
是这样做的。如果你只是为了提高效率而这样做,你要么是过度优化,要么不应该使用雄辩,因为它非常慢,而且资源非常繁重。遗憾的是,它不起作用,这段代码意味着你抓住了所有位置,但只为那些位于一楼的位置加载关系。
Place::join('locations', 'places.id', '=', 'locations.place_id')
->where('locations.floor', 1)
->select('places.*')
->get();