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!
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)]);
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 = [];
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();
Related
I migrated my database from Sql Server to MongoDB
I want to Join existing customer Table with contact Table .
Customer have multiple contacts . I tried whereRaw lookup
customer collection
{
"_id": 77,
"custid": 93
}
Contact Collection
{"_id":77,"contactid":77,"custid":93,"firstname":"Christy ","lastname":"Lambright" }
{"_id":79,"contactid":79, "custid":93,"firstname":"Marlys ","lastname":"Barry" }
Customer Modal
class custt extends Model
{
use Notifiable;
protected $primaryKey = 'id';
}
Contact Modal
class contact extends Model
{
use Notifiable;
protected $primaryKey = 'id';
In Controller
$cnt = DB::collection("custts")->raw(function($collection)
{
$more_where = [];
$more_where[]['$lookup'] = array(
'from' => 'contacts',
'localField' => 'custid',
'foreignField' => 'custid',
'as' => 'country',
);
return $collection->aggregate($more_where);
});
Error comes --
Empty Results
I tried Lots of options for hasMany and belongstoMany . Not working ...
please suggest
ok , finally found it working
source - https://github.com/jenssegers/laravel-mongodb/issues/841
$cnt = custt::raw(function($collection)
{
return $collection->aggregate(
[[
'$lookup' => [
'as'=>'info',
'from'=>'contacts',
'foreignField'=>'custid',
'localField'=>'custid'
]
]]
);
});
I have two models TeamMember and ProjectRequest.
A TeamMember can have one ProjectRequest, that is why I created the following Eloquent relationship on TeamMember:
class TeamMember extends Model {
//
protected $table = 'team_members';
protected $fillable = ['project_request_id'];
// Relations
public function projectTeam() {
return $this->hasOne('\App\Models\ProjectRequest', 'project_request_id');
}
}
In my Controller I want to query both tables, however it returns the failure message.
What is important to know is that $request->projectTeam is an array of emails, looking like this:
array:2 [
0 => "mv#something.com"
1 => "as#something.com"
]
Meaning that I need to bulk insert into team_members table the project_request_ id for each team member where the emails are in the array.
How can I do that in the right way? The following is my attempt:
public function createProjectTeam(Request $request){
try {
$title = $request->projectTitle;
$TeamMember = $request->projectTeam;
$projectRequest = ProjectRequest::create(['project_title' => $title]);
$projectRequestId = $projectRequest->id;
$projectTeam = $this->teamMembers->projectTeam()->create(['project_request_id'=> $projectRequestId])->where('email', $TeamMember);
//$projectTeam = TeamMember::createMany(['project_request_id' => $projectRequestId])->where($TeamMember);
//dd($projectTeam);
return $projectRequest.$projectTeam;
} catch(\Exception $e){
return ['success' => false, 'message' => 'project team creation failed'];
}
}
There are a few things you can do.
Eloquent offers a whereIn() method which allows you to query where a field equals one or more in a specified array.
Secondly, you can use the update() method to update all qualifying team members with the project_request_id:
public function createProjectTeam(Request $request)
{
try {
$projectRequest = ProjectRequest::create(['project_title' => $request->projectTitle]);
TeamMember::whereIn('email', $request->projectTeam)
->update([
'project_request_id' => $projectRequest->id
]);
return [
'success' => true,
'team_members' => $request->projectTeam
];
} catch(\Exception $e) {
return [
'success' => false,
'message' => 'project team creation failed'
];
}
}
I hope this helps.
I need to update the database table according to the edited data.
controller
public function update(Request $request)
{
$subscriptionplan = SubscriptionPlan::find($request->id);
$subscriptionplan->update($request->all());
return back();
}
But nothing happens when I submit the form. When I use dd($request->all()); at the beginning of the function, it correctly shows the edited data as follows.
array:10 [▼
"_method" => "patch"
"_token" => "gOCL4dK6TfIgs75wV87RdHpFZkD7rBpaJBxJbLHF"
"editname" => "SUP_EVA_001"
"editdesc" => "des"
"editprice" => "1000.050"
"editlimit" => "1"
"editperunit" => "20.000"
"editexceedunit" => "30.000"
"productid" => "1"
"id" => "1"
]
But database has not been updated.
My table name is Table: subscription_plans and model is SubscriptionPlan
These are the table columns:
protected $fillable = [
'name',
'description',
'price',
'usage_limit',
'charge_per_unit',
'charge_per_unit_exceed',
'is_limit_exceed_considered',
'product_id'
];
Any idea on how to solve it or what I have done wrong?
If your solution did not work, try the 1by1 like this.
public function update(Request $request)
{
$subscriptionplan = SubscriptionPlan::find($request->id);
$subscriptionplan->_method = $request->_method;
$subscriptionplan->_token = $request->_token;
$subscriptionplan->editname = $request->editname;
$subscriptionplan->editdesc = $request->editdesc;
$subscriptionplan->editprice = $request->editprice;
$subscriptionplan->editlimit = $request->editlimit;
$subscriptionplan->editperunit = $request->editperunit;
$subscriptionplan->editexceedunit = $request->editexceedunit;
$subscriptionplan->productid = $request->productid;
$subscriptionplan->save();
return back();
}
In order for Laravel to automatically fill the model attributes, the indexes of the array passed to the fill method must correspond to your model attributes names.
Also, instead of
$subscriptionplan->update($request->all());
Use
$subscriptionplan->fill($request->all());
Then save the subscription plan with $subscriptionplan->save();
I use audit-stash plugin which works fine with all my tables. But I have a particular function in which the user selects rows with checkboxes, and then changes a specific field to all of them. The table audits contains a fields called "primary_key" which seems not working for such case.
in my Controller, function, I put this:
$this->request->data;
$data = $this->request->data;
if($this->request->is(['patch', 'post', 'put']))
{
$ids = $this->request->data('data.AssetsAssignations.id');
$room_id = $this->request->data('room_id');
$this->AssetsAssignations->updateAll(
['room_id ' => $room_id ],
['id IN' => $ids]
);
}
in my table, I used this:
$this->addBehavior('AuditStash.AuditLog');
I was told that there is no way around this for audit-stash, because updateAll bypasses model callbacks by directly sending a query to the database.
I was suggested to update records one by one if I need to keep the log.
How can I transform my updateAll() code into a Save() loop ?
This try did not work for me, using save() and saveMany() :
$this->request->data;
$data = $this->request->data;
if($this->request->is(['patch', 'post', 'put']))
{
$ids = $this->request->data('data.AssetsAssignations.id');
$asset_status_id = $this->request->data('asset_status_id');
foreach($ids as $id) {
$this->AssetsAssignations->saveMany(
['asset_status_id ' => $asset_status_id ]
);
}
}
thanks in advance.
Actually you don't have to call get($id) for every id. This get the entity from the table and causes a lot of useless queries
if($this->request->is(['patch', 'post', 'put']))
{
$ids = $this->request->data('data.AssetsAssignations.id');
$asset_status_id = $this->request->data('asset_status_id');
$assetsAssignationsTable = TableRegistry::get('AssetsAssignations');
foreach($ids as $id) {
$assetsAssignation = $assetsAssignationsTable->newEntity(); // returns an empty entity
$assetsAssignation->id = $id; // assign the id to the entity
$assetsAssignation->asset_status_id = $asset_status_id;
$assetsAssignationsTable->save($assetsAssignation);
}
}
Thanks to Greg, this code worked for me:
use Cake\ORM\TableRegistry;
...
if($this->request->is(['patch', 'post', 'put']))
{
$ids = $this->request->data('data.AssetsAssignations.id');
$asset_status_id = $this->request->data('asset_status_id');
$assetsAssignationsTable = TableRegistry::get('AssetsAssignations');
foreach($ids as $id) {
$assetsAssignation = $assetsAssignationsTable->get($id); // Return assetsAssignation with id
$assetsAssignation->asset_status_id = $asset_status_id;
$assetsAssignationsTable->save($assetsAssignation);
}
}
is there any way to ignore the first result record in Yii2 at a query? I have a list of numbers that represents a client. For designing purposes i had to query the first record separatly but now i have it duplicated. My questin is how can I query in Yii2 to ignore the first result?
Regards,
Gábor
The second find is the query where i need to ignore the first result:
public function actionGeneratePage() {
public function actionGeneratePage() {
$behivott = Sorszam::find()->with('ablak')
->orderBy(['behivas_datum' => SORT_DESC])
->limit(1)
->all();
$sorszamok = Sorszam::find()->with('ablak')
->orderBy(['behivas_datum' => SORT_DESC])
->limit(4)
->all();
$reklam = Reklam::find()->all();
return $this->render('generatePage', [
'sorszamok' => $sorszamok,
'reklam' => $reklam,
'behivott' => $behivott,
]);
}
You use offset() to skip the first record:
$sorszamok = Sorszam::find()->with('ablak')
->orderBy(['behivas_datum' => SORT_DESC])
->limit(4)
->offset(1)
->all();
Also you can use a single query to get both $behivott and $sorszamok with array_shift:
$sorszamok = Sorszam::find()->with('ablak')
->orderBy(['behivas_datum' => SORT_DESC])
->limit(5)
->all();
$behivott = array_shift($sorszamok);