使用透视表的Laravel 5 BelongAsmany搜索
我正在使用Laravel的使用透视表的Laravel 5 BelongAsmany搜索,laravel,many-to-many,laravel-5.1,Laravel,Many To Many,Laravel 5.1,我正在使用Laravel的和一个pivot表来链接模型。然而,我使用的范围界定创建了一个非常低效的查询。这是我的密码: 餐厅班级 class Restaurant extends Model { public function cuisines() { return $this->belongsToMany('Cuisine'); } public function scopeByCity($query, $city_id) { r
和一个pivot表来链接模型。然而,我使用的范围界定创建了一个非常低效的查询。这是我的密码:
餐厅
班级
class Restaurant extends Model {
public function cuisines() {
return $this->belongsToMany('Cuisine');
}
public function scopeByCity($query, $city_id) {
return $query->where('city_id' '=', $id);
}
public function scopeByCuisine($query, $cuisine_id) {
return $query->whereHas('cuisines', function($q) use ($cuisine_id) {
$q->where('id', '=', $cuisine_id);
});
}
}
class Cuisine extends Model {
public function restaurants() {
return $this->belongsToMany('Restaurant');
}
}
烹饪
课程
class Restaurant extends Model {
public function cuisines() {
return $this->belongsToMany('Cuisine');
}
public function scopeByCity($query, $city_id) {
return $query->where('city_id' '=', $id);
}
public function scopeByCuisine($query, $cuisine_id) {
return $query->whereHas('cuisines', function($q) use ($cuisine_id) {
$q->where('id', '=', $cuisine_id);
});
}
}
class Cuisine extends Model {
public function restaurants() {
return $this->belongsToMany('Restaurant');
}
}
现在,Restaurant::byCity(1)->bycourine(2)->toSql()
给了我:
select * from `restaurants` where `city_id` = ? and (select count(*) from `cuisines` inner join `restaurants_cuisines` on `cuisines`.`id` = `restaurants_cuisines`.`cuisine_id` where `restaurants_cuisines`.`restaurant_id` = `restaurants`.`id` and `id` = ?) >= 1
执行时间是优化查询的3倍:
select * from `restaurants` left join `restaurants_cuisines` on `restaurants`.`id` = `restaurants_cuisines`.`restaurant_id` left join `cuisines` on `cuisines.id` = `restaurants_cuisines`.`cuisine_id` where `restaurants`.`city_id` = ? and `cuisines`.`id` = ?
这是Laravel的查询生成器的一个限制还是我做错了
更新
我现在已经将@Zoe Blair的答案标记为正确答案,但我仍然需要根据需要修改它。对于任何处于类似情况的人,以下是最终的解决方案:
public function scopeByCuisine($query, $cuisine=null) {
return $query->leftJoin('restaurants_cuisines', 'restaurants.id', '=', 'restaurants_cuisines.restaurant_id')
->leftJoin('cuisines', 'cuisines.id', '=', 'restaurants_cuisines.cuisine_id')
->where('cuisines.id', '=', $cuisine);
}
正如她在回答中所建议的,Laravel将从所有表中合并所有列,所以我也这样做了:
$sql = Restaurant::select('restaurants.*')->byCity($city_id)->byCuisine($cuisine_id)->toSql
这正是我想要的 您可以调整查询范围以使用联接:
public function scopeByCity($query, $city_id) {
return $query->leftJoin('cities', 'cities.id', '=', 'restaurants.city_id')
->where('city_id' '=', $city_id);
}
public function scopeByCuisine($query, $cuisine_id) {
return $query->leftJoin('cuisines', 'cuisines.id', '=', 'restaurants.cuisine_id')
->where('cuisine_id' '=', $cuisine_id);
}
我相信eloquent默认会返回所有列,因此在调用查询范围之前,我会将其限制为Restaurant::select('restaurants.')
,然后通过使用with('courine',city')
加在一起:
$restaurants = Restaurant::select('restaurant.*')
->city(4)
->cuisine(3)
->with('cuisine', 'city')
->get();
明亮的即使我不得不修改你的答案,以适应我在这种特殊情况下的需要,我仍然会接受它作为正确的答案。谢谢