1

I have mysql db with column that called "info", this is json column. I have there this json:

{ 
   "pizza":{ 
      "sugar":"yes",
      "calorie":"100",
      "protein":"no"
   },
   "hamburger":{ 
      "sugar":"no",
      "calorie":"120",
      "protein":"yes"
   }
}

when I want to update for example the calorie of the pizza there is no problem:

DB::table('food')->where('id', '=', '1')
    ->update(array('info->pizza->calorie' => '90'));

then in the db i have:

{ 
   "pizza":{ 
      "sugar":"yes",
      "calorie":"90",
      "protein":"no"
   },
   "hamburger":{ 
      "sugar":"no",
      "calorie":"120",
      "protein":"yes"
   }
}

but when i want to add some food, for example chocolate:

DB::table('food')->where('id', '=', '1')
    ->update(array('info->chocolate->calorie' => '10'));

nothing happened.

In which way I can do that? thanks!

2
  • I see a pizza object, but I don't see a chocolate object anywhere in your code. Commented Sep 8, 2019 at 13:33
  • @UdoE. there is no chocolate in the code. i want to add the chocolate like the pizze and the hamburger... Commented Sep 8, 2019 at 14:09

3 Answers 3

1

You can't update non-existing keys for json columns in MySQL table. Look at this post to better understand the reason why.

To solve this problem, your best bet is to retrieve the column json data, decode it, insert new object entry, encode it again and finally update the table with the new json data.

$food = DB::table('food')->where('id', '=', '1')->first();
$info = json_decode($food->info);
$info->chocolate = (object)["calorie"=>"10"];

DB::table('food')->where('id', '=', '1')
    ->update(['info' => json_encode($info)]);

Sign up to request clarification or add additional context in comments.

Comments

1

Which version of Laravel are you using? I'm able to set new keys in JSON cast columns using both 5.7 and 5.8:

User Model:

protected $casts = [
   'phone_numbers' => 'json',
];

Updating:

User::first()->phone_numbers;

[ 'mobile' => '0000000000', ]

User::first()->update(['phone_numbers->office'] => '9999999999']);
User::first()->phone_numbers;

[ 'mobile' => '0000000000', 'office' => '9999999999', ]

Updating nested values:

User::first()->update(['phone_numbers->office->ext'] => '100']);
User::first()->phone_numbers;

[ 'mobile' => '0000000000', 'office' => [ 'ext' => '100', ], ]

Edit: You don't happen to have $fillable set for the info column, do you? If so, I believe you'll have to specify each individual property for mass-assignment:

protected $fillable = [
    'info->chocolate',
];

You can test it quickly by removing it from $fillable and setting $guarded to an empty array (temporarily):

protected $guarded = [];

1 Comment

There are slightly more opening square brackets than closing brackets. And by the way it doesn't work in laravel 8
0

I know this is the exact answer, as 2 queries have to be performed on DB. But this is a workaround.

$food = DB::table('food')->where('id', '=', '1')->first();
$info = json_decode($food->info, true);
$info['chocolate']['calorie] = 10;
$food->info = json_encode(json_encode($info), JSON_FORCE_OBJECT);
$food->save();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.