Search code examples
phplaravelpivotmany-to-many

Laravel syncing multiple relations plus pivot data excluding empty data


I have a many-to-many relation, Recipes and Ingredients. I am trying to sync multiple ingredients to a recipe. I have an edit form where I send a recipe and a list of all ingredients.

In my ingredient_recipe table I have two extra pivot columns, number1 and number2.

In my form I have two dropdowns, simplified below:

<select name="{{ $ingredient->id }}[number1]">
    <option></option> // Empty value
    <option value="example1">Example 1</option>
    <option value="example2">Example 2</option>
</select>

<select name="{{ $ingredient->id }}[number2]">
    <option></option> // Empty value
    <option value="example1">Example 1</option>
    <option value="example2">Example 2</option>
</select>

When submitting the form, I get the following results:

array:2 [▼
  1 => array:2 [▼
    "number1" => example1
    "number2" => example2
  ]
  2 => array:2 [▼
    "number1" => example2
    "number2" => example1
  ]
]

In my controller's update method I am doing the following to sync the ingredients to the recipe:

$recipe->ingredients()->sync($ingredients);

Where $ingredients is the output of the request posted above.

While this does work flawlessly, it also syncs the values that have no selection in the dropdowns, because the $ingredient->id will always be submitted.

I have two questions about how I am approaching this.

  1. My main question is, how to avoid that ingredients with empty dropdown values get synced?
  2. It seems like a wrong solution to what I want to achieve I think, if so, any pointers in the right direction?

Solution

  • What I ended up doing is the following:

    foreach($ingredients as $key => $value)
    {
        if(is_null($value['number1']) || is_null($value['number2']))
        {
            unset($ingredients[$key]);
        }
    }
    

    This checks if either number1 or number2 is empty and if so, it removes the whole ingredient from the array so only selected values will be synced.