使用透视表的Laravel 5 BelongAsmany搜索

使用透视表的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

我正在使用Laravel的
和一个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();

明亮的即使我不得不修改你的答案,以适应我在这种特殊情况下的需要,我仍然会接受它作为正确的答案。谢谢