12

What I am trying to do is to update or insert the row in table. In my case, update looks something like this:

\DB::table('inventories')->where('product_code',$product_code)->increment('stock_current_quantity',$quantity);

I don't want to use if else statement. What I actually want is to integrate increment into following statement so it update as above statement.

 \App\Inventory::updateOrCreate(['product_code' => $product_code], ['stock_current_quantity'=>$quantity]);

Thanks in advance!

Nishal Gurung
  • 451
  • 2
  • 5
  • 20

6 Answers6

25

Because google brought me here and I think the answers here, especially when you simply want to use updateOrCreate, are not as satisfying as this:

\App\Inventory::updateOrCreate([
         'product_code' => $product_code
    ], 
    [
         'stock_current_quantity' => \DB::raw('stock_current_quantity + 1')
    ]
);

Credits to this guy

tomstig
  • 379
  • 4
  • 4
  • if you use these code ,you can get an error like this: Eloquent update with DB::raw triggers Object of class Illuminate/Database/Query/Expression could not be converted to int – gouki Dec 27 '19 at 01:48
  • 2
    It doesn't work at create (actually `INSERT`) because the field `stock_current_quantity` is not yet set. – DevonDahon Nov 16 '20 at 08:47
14

Why not do:

$inventory = \App\Inventory::firstOrNew(['product_code' => $product_code]);

$inventory->stock_current_quantity = ($inventory->stock_current_quantity + $quantity);
$inventory->save();

If the model doesn't exists, $inventory->stock_current_quantity will only be equal to $quantity, else, it will increment it by $quantity.

  • 1
    There's a small risk that the database `stock_current_quantity` might change in between retrieving the item and saving it though. That's why `increment` is safer to use – andrewtweber Oct 17 '15 at 10:47
  • Yup. There's that. If that's a concern and `product_code` is a unique index and MySQL is the only DBMS used, perhaps an `insert ... on duplicate key update` statement is more appropriate. – Sandyandi N. dela Cruz Oct 17 '15 at 11:06
  • this may cause raise conditions. Its better to use tomstig's method – Adam Jul 09 '19 at 13:29
12

I am using Laravel 7.8.1 and rolling it all into one statement as per the following works fine:

    $user->league_entries()->updateOrCreate([
        'month' => $month,
        'year' => $year
    ])->increment('score');
Inigo
  • 8,110
  • 18
  • 62
  • 110
1

just contributing if someone else has this problem

it doesn't exist, creates, but with zero

self::firstOrNew(['product_code' => $product_code]);

then, increment it... if other process updates it to 1 before me (in this middle time between firstOrNew and increment), this will update to 2, avoiding losing the prior update

self::where('product_code', $product_code)->increment('stock_current_quantity');
Jayendran
  • 9,638
  • 8
  • 60
  • 103
1

Similar to Inigo's answer, but slight change i would go with:

 $user->league_entries()->firstOrCreate([
        'month' => $month,
        'year' => $year
    ])->increment('score');
Jimmy Miller
  • 51
  • 1
  • 3
0
Model::updateOrInsert([
 "name" => "last_run21",
 ], [
 "value" => DB::raw("IF(ISNULL(value + 1),1,value+1)"),
]);

This basically either creates the entry with name == "last_run21" with a initial value of 1 or updates it with value+1.

Tested on Mysql.