Обновление отношений один-ко-многим с помощью Eloquent в Laravel - PullRequest
0 голосов
/ 22 мая 2018

Я относительно новичок в Laravel.Я пытаюсь выяснить, как использовать транзакции с Eloquent ORM, особенно когда дело касается отношений.

Допустим, у меня есть отношение один ко многим между двумя таблицами: Recipes и Ingredients соответственно.

Один рецепт (с его ингредиентами) выглядит следующим образом:

[
    'id' => 1,
    'name' => 'Lasagna',
    'readyIn' => '30 minutes',
    'ingredients' => [
        ['id' => 1, 'name' => 'noodles', 'quantity' => '8'],
        ['id' => 2, 'name' => 'cheese', 'quantity' => '2 cups']
    ]
]

При обновлении существующего рецепта мне приходит запрос:

[
    'id' => 1,
    'name' => 'Lasagna',
    'readyIn' => '1 hour',
    'ingredients' => [
        ['id' => 1, 'name' => 'noodles', 'quantity' => '9'],
        ['id' => 2, 'name' => 'mozarella cheese', 'quantity' => '3 cups'],
        ['id' => null, 'name' => 'sauce', 'quantity' => '1 jar'],
        ['id' => null, 'name' => 'onion', 'quantity' => '1']
    ]
]

Мой подходдля обновления рецепта нужно было сделать следующее:

DB::transaction(function() use ($request, $id) {
    // update existing recipe
    $recipe = Recipe::find($id);
    $recipe->fill($request->all());
    $recipe->save();

    // get old & new ingredients
    $oldIngredients = $recipe->ingredients();
    $newIngredients = $request->get('ingredients');

    // delete old ingredients that do not appear in the new list
    if ($ids = array_diff(
        array_pluck($oldIngredients, 'id'),
        array_pluck($newIngredients, 'id')
    )) {
        Ingredient::destroy($ids);
    }

    // save new ingredients
    foreach ($newIngredients as $attributes) {
        // update existing ingredient
        if ($id = array_pull($attributes, 'id')) {
            $ingredient = Ingredient::find($id);
            $ingredient->fill($attributes);
            $ingredient->save(); 
        // create new ingredient
        } else {
            $recipe->ingredients()->create($attributes);
        }
    }
});

Насколько я понимаю, при использовании этого подхода не будет разногласий между теми, кто находится в таблице Ingredients, и ингредиентами $recipe.?Как и в Ingredient::destroy($ids) и $ingredient->save(), изменяются только записи в таблице Ingredients, но не ингредиенты $recipe.Если да, есть ли способ обновить $recipe при обновлении или удалении ингредиентов?Моя цель - обновить $recipe, включая его компоненты, после завершения транзакции.

...