我有两个模型:食品和设备。 这两个模型是多对多关系(也处理了我的 Laravel Eloquent)。所以 Food 有一些必要的设备来准备它。
我想要过滤食物,其中包含输入时给出的所有设备,并且不需要此食物的任何其他设备。所以换句话说 - 当输入设备包含在与某些食物相关的设备中时。
想法展示示例
例如,我有一个名为“Xyz 蛋糕”的 sample 食品。要准备这种食物,您需要
- 搅拌器
- toastr
假设我们有以下设备的输入:
- 搅拌器
- 厨房机器人
- toastr
在这种情况下,过滤脚本应该将我们的食物带入结果,因为与食物相关的设备适合输入设备。
另一个例子:“Abc 蛋糕”。所需设备:
- blender
- 厨房机器人
- toastr
输入设备:
- blender
- 厨房机器人
在这种情况下,脚本不应将 Food 带入结果,因为要准备 Food 还需要 toastr ,但输入设备中不存在 toastr 。
我当前的代码
$equipments 变量是包含输入设备 ID 的数组。
$query = Food::query();
$query->join('equipments_foods', function ($join) use ($equipments) {
$join->on('foods.id', '=', 'equipments_foods.food_id');
$join->whereIn('equipments_foods.equipment_id', $equipments);
});
$results = $query->get();
此代码无法正常工作,因为它从输入设备中提供至少包含一件设备的食物。
数据库是MySQL。
请帮助我实现正常工作的过滤。
非常感谢!
最佳答案
我认为以下内容可以解决您的问题。这是一个用于测试的 SQL Fiddle。 http://sqlfiddle.com/#!9/d04555/3
基本上,它将问题抛到脑后,使用非选定设备查找并排除所有食物。
SELECT f.*
FROM food f
WHERE NOT EXISTS (
SELECT *
FROM equipment e
INNER JOIN equipments_foods ef ON (e.id = ef.equipment_id)
WHERE e.id NOT IN (1, 2, 3)
AND f.id = ef.food_id
)
然后您可以创建一个模型查询范围来包含此逻辑。以下是使用 Laravel 的查询构建器编写此内容的未经测试的尝试。
$foods = Food::usingEquipment($equipment)->get();
public function scopeUsingEquipment(Builder $query, array $equipment)
{
return $query->whereNotExists(function ($query) use ($equipment) {
$query->select(DB::raw(1))
->from('equipment')
->join('equipments_foods', 'equipment.id', '=', 'equipments_foods.equipment_id')
->whereIn('equipment.id', $equipment)
->whereRaw('food.id = equipments_foods.food_id');
});
}
关于php - Laravel:排除对多对多关系的过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47146848/