我有两种模式:食物和设备。这两个模型是由多对多关系(也处理了我的Laravel雄辩)。所以食物有一些必要的设备来准备它。
我想要含有所有输入设备的过滤食品,并且这种食品不需要任何其他设备。换句话说,当输入设备包含在与某些食物相关的设备中时。
例如,我有一种叫做“Xyz蛋糕”的食物样本。准备你需要的食物
假设我们输入了以下设备:
在这种情况下,过滤脚本应该将我们的食物输入结果,因为与食物相关的设备适合输入设备。
另一个例子:“abc蛋糕”。所需设备:
输入设备:
在这种情况下,脚本不应将食物纳入结果,因为准备食物还需要烤箱,但输入设备中不存在烤箱。
$设备变量是包含输入设备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小提琴可以测试。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');
});
}
我建议您使用laravel的多对多数据透视表。你的食物模型应该是这样的
名称空间应用程序;
使用Illumb\Database\Elount\Model;
类扩展模型{protected$filleble=['name'];
公共功能设备(){
退还$this
}
公共函数范围(查询){
返回$查询-
}
food_equipment是透视表,food_id和equipment_id是透视表中的字段。这种关系确保了生产不同种类食品所需的所有设备都能适当匹配。
scopeRel是一个本地范围,它将返回在阵列中准备食物所需的所有设备。
您可以查询模型。Food::凡('equipment_id',1)─
经过研究,找到正确的解决方案,最后我设法让它使用Laravel查询生成器工作。
我觉得没那么容易。
$query = Food::query();
$query->where(function ($query) use ($inputEquipment) {
$query->doesntHave('equipments');
$query->orWhere(function ($query) use ($inputEquipment) {
foreach ($inputEquipment as $equipmentId) {
$query->whereHas('equipments', function ($query) use ($equipmentId) {
$query->where('id', $equipmentId);
});
}
});
});
$results = $query->get();