I'm trying this for a while now and I can't seem to figure it out.
So I have a Products and a Sizes table with a belongs to many relation.
So in my model I have:
public function sizes()
{
return $this->belongsToMany(Size::class, 'size_product')->withPivot('price');
}
<h2 class="fields-holder__title">Sizes</h2>
@foreach($sizes as $size)
<div class="field-holder__container">
<input type="checkbox" name="sizes[]" value="{{ $size->id }}">
<input type="text" name="prices[]" placeholder="Price">
</div>
@endforeach
// add and remove sizes pivot
$sizes = [];
foreach ($request->sizes as $size) {
array_push($sizes, $size);
}
$product->sizes()->sync($sizes);
$product->sizes()->sync($size, ['price' => $price]);
First of all, the logic for saving the Product with it's corresponding sizes/prices doesn't belong in your Controller, but in your Model (or some intermediate data layer).
As for your issue: you can only save pivot relations to a record that already has an id, ie. one that has already been saved to the database. Also, the sync()
method on the belongsToMany class is meant for saving multiple relations by ids, and accepts a boolean as a second argument (whether to detach or not, default is true).
In this case you should do a foreach over the array of sizes, an attach()
each one, with it's price, to the parent model. Something like this:
ProductsController.php
public method store(Request $request)
{
// call the create method on the model
$product = Product::createForSizes(
$request->only('name', 'sizes', 'prices')
);
return $product
? redirect()->route('some.route')
: redirect()->route('some.other.route');
}
Product.php
public static method createForSizes($name, array $sizes, array $prices)
{
// create and save a new instance of the model
if(!$product = static::create(compact('name'))) {
return false;
}
// attach each size, with it's price
foreach($sizes as $index => $id) {
$price = isset($prices[$index]) ? $prices[$index] : null;
$product->sizes()->attach($id, compact('price'));
}
return $product;
}
Note: Laravel looks for pivot tables automatically if you name them as plural, in alphabetical order. So if you name your pivot table products_sizes, you can omit the table name from the relation method like so:
public function sizes()
{
return $this->belongsToMany(Size::class)->withPivot('price');
}