Reputation: 39
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!
Upvotes: 1
Views: 4875
Reputation: 11
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 = [];
Upvotes: 1
Reputation: 2823
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)]);
Upvotes: 1
Reputation: 825
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();
Upvotes: 0