Home > Software engineering >  How to sync with 2 main items in Laravel syncWithoutDetaching
How to sync with 2 main items in Laravel syncWithoutDetaching

Time:05-12

The Cart_product table has 4 columns:

id | cart_id | product_id | size_id | quantity

with relationship of belongsToMany for Cart, Product and Size.

User can add a product with deferent sizes but not same size, so product->id = 1 can have size->id = 1 and size->id = 2.

I want to sync product->id and size->id where only have 1 row of same product->id and size->id.

with this code, only my product->id is synced.

        $this->cart->products()->syncWithoutDetaching(
[$product->id => ['size_id' => $size->id, 'quantity' => $quantity]]
            );

As I said I need to sync product->id and size->id, I can have a product with deferent sizes:

id | cart_id | product_id | size_id | quantity
1  | 1       |1           | 2       |2
2  | 1       |1           | 3       |1

but not a product with same sizes:

id | cart_id | product_id | size_id | quantity
1  | 1       |1           | 2       |2
2  | 1       |1           | 2       |1

I have checked many cases as :

        $this->cart->products()->syncWithoutDetaching(
[$product->id, $size->id => ['quantity' => $quantity]]
            );

But it can't take true result!

CodePudding user response:

BelongsToMany relation are made for pivot tables with only two foreign keys as their unicity index. In your case, the unicity is obtained with three indexes cart_id, product_id and size_id so you can't use any predefined method from the relation to achieve your goal.

side note: I suggest you add this constraint in your database so it triggers an error if your code tries to insert two rows with the same values in those indexes

To sync with three indexes I suggest you use updateOrInsert() or upsert()

\DB::table('your_pivot_table_name')->updateOrInsert(
    ['cart_id' => 1, 'product_id' => 1, 'size_id' => 2], //the unique index to look out for
    ['quantity' => 2] //the other fields to sync
);

Another idea would be to declare the pivot table as Custom Intermediate Table Models and add the method to "sync" using updateOrCreate() to it.

EDIT: upsert

DB::table('cart_product')->upsert(
    [
        [ 'cart_id' => $this->instance()->id, 'product_id' => $product->id, 'size_id' => $size->id, 'quantity' => (int) $qunatity]
    ], 
    ['cart_id', 'product_id', 'size_id'], 
    ['quantity']
);
  • Related