在 Laravel 9.x 中批量创建/更新中间枢轴属性
我正在构建一个膳食计划程序,它可以自动创建购物清单,其中关键的事情之一是能够设置食谱上成分的数量。我通过在 Recipe ->; 之间的枢轴上使用中间值来做到这一点成分
。这是在我的中间枢轴模型 IngredientRecipe 中定义的,它存储一个单位和一个单位。食谱所需的数量。
Recipe -> IngredientRecipe(Quantity,Unit) -> Ingredient
我在设置每种成分的数量和单位时遇到问题。我知道我可以在创建每个对象后单独循环和迭代它们;然而,这感觉不对,我宁愿在单个查询中完成它。
我对如何继续这件事有点困惑。我本以为用设置的值初始化一堆 IngredientRecipe 枢轴并将它们保存到配方中就足够了,但枢轴值没有保留。这一切都是在 PHP 8.1 上使用 Laravel 9.2 构建的。
Recipe.php
...
public function ingredients(): BelongsToMany
{
return $this->belongsToMany(Ingredient::class)
->using(IngredientRecipe::class);
}
IngredientRecipe.php
...
protected $fillable = [
'recipe_id',
'ingredient_id',
'quantity',
'unit_id',
];
public function recipe(): BelongsTo
{
return $this->belongsTo(Recipe::class);
}
public function ingredient(): BelongsTo
{
return $this->belongsTo(Ingredient::class);
}
public function unit(): BelongsTo
{
return $this->belongsTo(Unit::class);
}
UpdateIngredientRecipe.php
...
return [
'unit' => 'required|array',
'quantity' => 'required|array',
'unit.*' => 'integer|exists:units,id',
'quantity.*' => 'numeric|digits_between:0,999',
];
IngredientRecipeController.php
...
public function update(Recipe $recipe, UpdateIngredientRecipe $request): RedirectResponse
{
$pivots = collect($request->validated('quantity'))
->map(function (float $quantity, int $ingredient_id) use ($request, $recipe): IngredientRecipe {
$payload = [
'ingredient_id' => $ingredient_id,
'recipe_id' => $recipe->id,
'quantity' => $quantity,
'unit_id' => (int) $request->validated('unit')[$ingredient_id],
];
return IngredientRecipe::make($payload);
});
$recipe->ingredients()->attach($pivots->pluck('ingredient_id'), $pivots->first()->toArray());
dd(__METHOD__, $recipe->fresh('ingredients')->ingredients);
return redirect()->route('recipe.get', $recipe);
}
I'm building a meal planner that automatically creates a shopping list, and one of the key things is being able to set the quantity of an ingredient on a recipe. I'm doing this by using intermediate values on my pivot between Recipe -> Ingredients
. This is defined in my intermediate pivot model, IngredientRecipe, which stores a unit & quantity that the recipe needs.
Recipe -> IngredientRecipe(Quantity,Unit) -> Ingredient
I'm having an issue setting the quantity and unit for each ingredient. I know that I could loop and iterate through each one individually after they're created; however, that just feels wrong, and I'd instead do it in a single query.
I'm a bit stuck on how to proceed with this. I would have thought initializing a bunch of IngredientRecipe pivots with their values set and just saving them to the Recipe would be enough, but the pivot values aren't preserved. This is all built with Laravel 9.2 on PHP 8.1.
Recipe.php
...
public function ingredients(): BelongsToMany
{
return $this->belongsToMany(Ingredient::class)
->using(IngredientRecipe::class);
}
IngredientRecipe.php
...
protected $fillable = [
'recipe_id',
'ingredient_id',
'quantity',
'unit_id',
];
public function recipe(): BelongsTo
{
return $this->belongsTo(Recipe::class);
}
public function ingredient(): BelongsTo
{
return $this->belongsTo(Ingredient::class);
}
public function unit(): BelongsTo
{
return $this->belongsTo(Unit::class);
}
UpdateIngredientRecipe.php
...
return [
'unit' => 'required|array',
'quantity' => 'required|array',
'unit.*' => 'integer|exists:units,id',
'quantity.*' => 'numeric|digits_between:0,999',
];
IngredientRecipeController.php
...
public function update(Recipe $recipe, UpdateIngredientRecipe $request): RedirectResponse
{
$pivots = collect($request->validated('quantity'))
->map(function (float $quantity, int $ingredient_id) use ($request, $recipe): IngredientRecipe {
$payload = [
'ingredient_id' => $ingredient_id,
'recipe_id' => $recipe->id,
'quantity' => $quantity,
'unit_id' => (int) $request->validated('unit')[$ingredient_id],
];
return IngredientRecipe::make($payload);
});
$recipe->ingredients()->attach($pivots->pluck('ingredient_id'), $pivots->first()->toArray());
dd(__METHOD__, $recipe->fresh('ingredients')->ingredients);
return redirect()->route('recipe.get', $recipe);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
所以我自己解决了这个问题。回想起来,这似乎是显而易见的痛苦,但我希望这可以帮助那些将来陷入类似问题的人。
我现在正在构建一个由 Ingredient ID 键控的数据透视属性数组,
因此从某种意义上说,我现在正在做的是:
还值得注意的是,我需要更新 Ingredient ID 中的关系定义>获取枢轴值的方法
So I've solved this by myself. Seems painfully obvious in retrospect but I hope this helps someone who gets stuck on a similar thing in future.
I'm now building an array of the pivot attributes keyed by the Ingredient ID
so in a sense what I'm doing now is:
It's also worth noting that I needed to update my relationship definition in Recipe in order to get the pivot values
这对于您的用例来说应该足够了:
由于关系数据已经在数据透视数组中,您也不需要附加它们。
createMany
可能能够批量插入行并节省多个数据库/服务器往返次数。This should be sufficient for your use case:
Since the relationship data is already in the pivot array you don't need to attach them as well.
createMany
may be able to mass insert rows and save on multiple db/server round-trips.