首页 > 解决方案 > Laravel:根据过敏原限制从数据库表中提取配方?

问题描述

我正在开发基于用户输入约束的膳食计划生成器。

这些限制之一是过敏原。我最初尝试有两个表,Recipes 和 Recipe_Allergens,因为一个食谱可以有许多过敏原,并通过食谱 ID 连接它们。

例如配方表:

ID 食谱名称 类型
1 烤宽面条 晚餐

例如 Recipe_Allergens 表:

ID 配方_ID 过敏原_描述
1 1 乳制品
2 1 麸质

用户输入表单都是下拉列表,除了过敏原是复选框。这就是为什么输入必须被内爆,然后再次爆炸:

$request->merge([
    'allergens' => implode(',', (array)$request->get('allergens'))
]);

$meal = $request->meal_type;
$allerg = $request->allergens;

$allergenarray2 = explode(",", $allerg);

然后我加入了这些表并进行了搜索,以便根据给定的用户饮食限制找到适当的食谱 ID:

$recipenew = Recipe::join('recipe_allergens', 'recipe_allergens.recipe_id', '=', 'recipe.id')
    ->where('recipe.type', $meal)
    ->whereNotIn('recipe_allergens.allergen_description', $allergenarray2)
    ->get('recipe.id');

添加到膳食计划表中:

$x = 0;
while ($x < $days) {
    $recipeday = (new Carbon($request->date))->addDays($x);
    $recidnew = $recipenew[$x]->id;
    MealPlanDisplay::create([
        'Recipe_ID' => $recidnew,
        'Day' =>  $recipeday,
        'user_id' => $currentuserid,
    ]);
    $x = $x + 1;
}

但是,问题是由于此数据库设置而出现逻辑错误。
如果用户同时输入“乳制品”和“麸质”作为他们的过敏症,则此方法有效。但是,如果用户只输入“乳制品”作为他们的过敏原,他们仍然会在他们的膳食计划中获得推荐的“千层面”,因为“麸质”和“食谱 ID”是单独隔离的。这很糟糕,因为千层面的配方中仍然含有乳制品。

还有什么其他的编程解决方案可以检查配方中可能含有多种过敏原的每种过敏原?

标签: phpdatabaselaraveleloquent

解决方案


要获取不包含过敏原的食谱,请使用Recipe::class模型和Allergen::class模型之间的关系

选项1

如果您不想更改结构,请将关系设置为hasMany

public function allergens()
{
    return $this->hasMany(Allergens::class, 'Recipe_ID');
}

并使用代码

$recipenew = Recipe::where('recipe.type', $meal)->whereDoesntHave('allergens', function($QBallergens) use($allergenarray2) {
    $QBallergens->whereIn('Allergen_Description',$allergenarray2);
})->pluck('id');

选项 2

更改多对多关系的结构。

所以你需要一个单独的表Allergens和一个allergen_recipe以 allergen_id 和 recipe_id 作为键的数据透视表。

public function allergens()
{
    return $this->belongsToMany(Allergens::class);
}

并使用“几乎”相同的代码(适用于 ids)。

$recipenew = Recipe::where('recipe.type', $meal)->whereDoesntHave('allergens', function($QBallergens) use($allergenarrayIds) {
    $QBallergens->whereIn('id',$allergenarrayIds);
})->pluck('id');

推荐阅读