ferares

ferares

Member Since 1 Year Ago

Experience Points
2,970
Total
Experience

2,030 experience to go until the next level!

In case you were wondering, you earn Laracasts experience when you:

  • Complete a lesson — 100pts
  • Create a forum thread — 50pts
  • Reply to a thread — 10pts
  • Leave a reply that is liked — 50pts
  • Receive a "Best Reply" award — 500pts
Lessons Completed
27
Lessons
Completed
Best Reply Awards
0
Best Reply
Awards
  • start your engines Created with Sketch.

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • first-thousand Created with Sketch.

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • 1-year Created with Sketch.

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • 2-years Created with Sketch.

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • 3-years Created with Sketch.

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • 4-years Created with Sketch.

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • 5-years Created with Sketch.

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • school-in-session Created with Sketch.

    School In Session

    Earned when at least one Laracasts series has been fully completed.

  • welcome-newcomer Created with Sketch.

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • full-time-student Created with Sketch.

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • pay-it-forward Created with Sketch.

    Pay It Forward

    Earned once you receive your first "Best Reply" award on the Laracasts forum.

  • subscriber Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • evangelist Created with Sketch.

    Laracasts Evangelist

    Earned if you share a link to Laracasts on social media. Please email [email protected] with your username and post URL to be awarded this badge.

  • chatty-cathy Created with Sketch.

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • lara-veteran Created with Sketch.

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • 10k-strong Created with Sketch.

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • lara-master Created with Sketch.

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • laracasts-tutor Created with Sketch.

    Laracasts Tutor

    Earned once your "Best Reply" award count is 100 or more.

  • laracasts-sensei Created with Sketch.

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • top-50 Created with Sketch.

    Top 50

    Earned once your experience points ranks in the top 50 of all Laracasts users.

Level 1
2,970 XP
Jun
30
1 week ago
Activity icon

Awarded Best Reply on Pivot Table Update: UpdateExistingPivot Or SyncWithoutDetaching? Neither Works

Well I found the problem and I feel like an idiot :V

updateExistingPivot takes, as its first argument, the id of the row on the related table, not the id of the row on the pivot table.

Final working code looks like this:

public function add()
{
    // Get the active cart from the session
    $cart = $this->request->cart;
    // Get the SKU of the product
    $sku = $this->request->sku;
    // Get the product or 404
    $product = Product::select(['id', 'price'])->where('sku', $sku)->firstOrFail();
    // Get the size & color
    $size = $this->request->size;
    $color = $this->request->color;
    // Get the quantity to add
    $quantity = $this->request->quantity;
    // Get or create the cart line
    // If there's already a line in the cart for this product
    // with the same size & color we just need to update its quantity
    $line = CartProduct::firstOrCreate([
        'product_id' => $product->id,
        'cart_id' => $cart->id,
        'size' => $size ? $size : '',
        'color' => $color ? $color : '',
    ]);
    // Set the new quantity
    $quantity += $line->quantity;
    // Save the changes
    $cart->products()->updateExistingPivot($line->product_id, ['quantity' => $quantity]);
    // Response
    return response()->json(['cart_total_quantity' => $cart->total_quantity]);
}

Thank you Vincent for all your time & help

Activity icon

Replied to Pivot Table Update: UpdateExistingPivot Or SyncWithoutDetaching? Neither Works

Well I found the problem and I feel like an idiot :V

updateExistingPivot takes, as its first argument, the id of the row on the related table, not the id of the row on the pivot table.

Final working code looks like this:

public function add()
{
    // Get the active cart from the session
    $cart = $this->request->cart;
    // Get the SKU of the product
    $sku = $this->request->sku;
    // Get the product or 404
    $product = Product::select(['id', 'price'])->where('sku', $sku)->firstOrFail();
    // Get the size & color
    $size = $this->request->size;
    $color = $this->request->color;
    // Get the quantity to add
    $quantity = $this->request->quantity;
    // Get or create the cart line
    // If there's already a line in the cart for this product
    // with the same size & color we just need to update its quantity
    $line = CartProduct::firstOrCreate([
        'product_id' => $product->id,
        'cart_id' => $cart->id,
        'size' => $size ? $size : '',
        'color' => $color ? $color : '',
    ]);
    // Set the new quantity
    $quantity += $line->quantity;
    // Save the changes
    $cart->products()->updateExistingPivot($line->product_id, ['quantity' => $quantity]);
    // Response
    return response()->json(['cart_total_quantity' => $cart->total_quantity]);
}

Thank you Vincent for all your time & help

Activity icon

Replied to Pivot Table Update: UpdateExistingPivot Or SyncWithoutDetaching? Neither Works

I'm going with this "not ideal" solution for now but I would love to understand what was wrong with my original approach and I'm willing to keep trying out suggestions of possible solutions :)

$line = CartProduct::select(['id', 'quantity'])
->where('product_id', $product->id)
->where('cart_id', $cart->id)
->where('size', $size ? $size : '')
->where('color', $color ? $color : '')
->first();

if ($line) {
    $line->quantity += $quantity;
    $line->save();
} else {
    CartProduct::create([
        'product_id' => $product->id,
        'cart_id' => $cart->id,
        'size' => $size ? $size : '',
        'color' => $color ? $color : '',
        'quantity' => $quantity,
    ]);
}
Activity icon

Replied to Pivot Table Update: UpdateExistingPivot Or SyncWithoutDetaching? Neither Works

I've also noticed that the object I get with firstOrCreate only has an id property if it finds a row in the DB, if the method had to add a new row then there's no id.

Activity icon

Replied to Pivot Table Update: UpdateExistingPivot Or SyncWithoutDetaching? Neither Works

Yeah, firstOrCreate inserts a new row into the DB but then I need to update it's quantity, that's why I need to do something else afterwards.

Activity icon

Replied to Pivot Table Update: UpdateExistingPivot Or SyncWithoutDetaching? Neither Works

Yeah I didn't express myself correctly, the product is the same but the method should create a new "line" if the color or the size are different.

Here's a different product

{
  "product_id":2,
  "cart_id":12,
  "color":"red",
  "size":"small",
  "updated_at":"2020-06-30T17:52:19.000000Z",
  "created_at":"2020-06-30T17:52:19.000000Z"
}  
Activity icon

Replied to Pivot Table Update: UpdateExistingPivot Or SyncWithoutDetaching? Neither Works

New product:

{
  "product_id":1,
  "cart_id":12,
  "color":"red",
  "size":"small",
  "updated_at":"2020-06-30T17:45:26.000000Z",
  "created_at":"2020-06-30T17:45:26.000000Z"
}

Same product again:

{
  "id":78,
  "cantidad":0,
  "color":"red",
  "size":"small",
  "product_id":1,
  "cart_id":12,
  "created_at":"2020-06-30T17:45:26.000000Z",
  "updated_at":"2020-06-30T17:45:26.000000Z"
}  

Other new product:

{
  "product_id":1,
  "cart_id":12,
  "color":"blue",
  "size":"small",
  "updated_at":"2020-06-30T17:45:52.000000Z",
  "created_at":"2020-06-30T17:45:52.000000Z"
}  
Activity icon

Replied to Pivot Table Update: UpdateExistingPivot Or SyncWithoutDetaching? Neither Works

Sure, (I did \Log::info($line) instead of dd):

{
	"id":77,
	"quantity":0,
	"size":"small",
	"color":"red",
	"product_id":1,
	"cart_id":12,
	"created_at":"2020-06-30T17:06:54.000000Z",
	"updated_at":"2020-06-30T17:06:54.000000Z"
}

The timestamps do not correspond to the time at which I ran the code (17:40 UTC) so it is getting an existing row from the DB, like I said until I try to edit the quantity everything works as expected

Activity icon

Replied to Pivot Table Update: UpdateExistingPivot Or SyncWithoutDetaching? Neither Works

Also, if I try to save the pivot table element on its own $line->save() (which I believe should have the same effect as syncing or updating existing pivot) I get the following error:

SQLSTATE[42S22]: Column not found: 1054 Unknown column '' in 'where clause' (SQL: update `cart_product` set `quantity` = 1, `cart_product`.`updated_at` = 2020-06-30 14:25:27 where `` = 1 and `` = 11) 

both cart_id and product_id column names are missing

Activity icon

Replied to Pivot Table Update: UpdateExistingPivot Or SyncWithoutDetaching? Neither Works

yeah I think you're right and I don't need the save/update call but I just deleted that line and the behavior is still the same for both updateExistingPivot() and syncWithoutDetaching()

Jun
29
1 week ago
Activity icon

Replied to Pivot Table Update: UpdateExistingPivot Or SyncWithoutDetaching? Neither Works

Thanks for taking the time to answer, I changed $cart->save() for $cart->update() and the results were the same :(

Activity icon

Started a new Conversation Pivot Table Update: UpdateExistingPivot Or SyncWithoutDetaching? Neither Works

Hi, I'm trying to update a column on a pivot table on a many to many relationship and nothing seems to work, maybe someone here can give me a hand with it :)

I have a "carts" table:

Schema::create('carts', function (Blueprint $table) {
    $table->id();
    $table->timestamps();
});

Then a "products" table:

Schema::create('products', function (Blueprint $table) {
      $table->id();
      $table->string('sku')->unique();
      $table->string('slug')->unique();
      $table->longText('name');
      $table->float('price');
      $table->timestamps();
  });

Finally I have a "cart_product" table:

Schema::create('cart_product', function (Blueprint $table) {
    $table->id();
    $table->index(
        ['product_id', 'cart_id', 'color', 'size'],
         'product_cart_color_size'
     );
    $table->integer('quantity')->unsigned()->default(0);
    $table->string('color')->default('');
    $table->string('size')->default('');
    $table->bigInteger('product_id')->unsigned();
    $table->bigInteger('cart_id')->unsigned();
    $table->timestamps();
});

Schema::table('cart_product', function (Blueprint $table) {
    $table->foreign('cart_id')->references('id')->on('carts')->onDelete('cascade');
    $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
});

And a relationship between the three defined in the Cart model:

// Cart model
public function products() {
    return $this->belongsToMany('App\Product')
      ->withTimeStamps()
      ->using('App\CartProduct')
      ->withPivot('quantity', 'color', 'size');
}

And in the CartProduct model:

// CartProduct model
public function product() {
    return $this->belongsTo('App\Product');
}

public function cart() {
    return $this->belongsTo('App\Cart');
}

The functionality I'm trying to implement is that users should be able to add products to the cart and if they add the same product more than once (same product, color and size) then the quantity on that cart line gets updated.

When a user adds a product to the cart, the controller handles that request with the following method:

public function add()
{
    // Get the active cart from the session
    $cart = $this->request->cart;
    // Get the SKU of the product
    $sku = $this->request->sku;
    // Get the product or 404
    $product = Product::select(['id', 'price'])->where('sku', $sku)->firstOrFail();
    // Get the size & color
    $size = $this->request->size;
    $color = $this->request->color;
    // Get the quantity to add
    $quantity = $this->request->quantity;
    // Get or create the cart line
    // If there's already a line in the cart for this product
    // with the same size & color we just need to update its quantity
    $line = CartProduct::firstOrCreate([
      'product_id' => $product->id,
      'cart_id' => $cart->id,
      'size' => $size ? $size : '',
      'color' => $color ? $color : '',
    ]);
    // Set the new quantity
    $quantity += $line->quantity;
    // .....

Everything seems to work until this point, when I actually try to persist the quantity update. (CartProduct::firstOrCreate works as expected and finds an existing line if there was one or creates a new one with its initial quantity set to 0).

I've tried 2 ways (with lots of variations for each one) of saving the quantity changes to the DB, first I tried with updateExistingPivot:

$cart->products()->updateExistingPivot($line->id, ['quantity' => $quantity]);
$cart->save();

Then with syncWithoutDetaching:

$cart->products()->syncWithoutDetaching([
    $line->id => [
          'quantity' => $quantity,
          'product_id' => $product->id,
          'cart_id' => $cart->id,
          'size' => $size ? $size : '',
          'color' => $color ? $color : '',
      ]
]);
$cart->save();

The solution using updateExistingPivot does not do anything at all.

The solution using syncWithoutDetaching actually inserts a new row into the pivot column each time, so it's not updating the quantity of a row, it just makes a duplicate and sets the quantity on that new one.

Both solutions return with no errors.

What am I missing?