I have the following ResearchModel (eloquent):
$research = new ResearchModel();
$research->id = 2;
$research->name = "test";
$research->save();
I am expecting Laravel to run an update statement (because I set the id), but it runs an insert statement instead.
$research->update(); wont do anything.
I don't want to use array in this case because I need the eloquent model events to be triggered.
I also don't want to run ResearchModel::find(2); before, this will cause significant performance problems in my use-case.
Is there any way to tell Laravel to update by the id?
Thanks
If you don't want to "select" first. Then you can update directly. This will run only one query.
$research = ResearchModel::where('id',2)->update([
'name' => 'test',
]);
A dirty solution:
// Create an instance without insert to database.
$instance = new ResearchModel;
$instance->id = 2;
$instance->name = "test";
// Set the instance status directly.
$instance->exists = true;
// Update database without model.
ResearchModel::where('id', $instance->id)
->update(['name' => $instance->name]);
// Manually trigger event.
event('eloquent.updating: App\ResearchModel', $instance);
The premise of this method is that you already have the required data. If the data required for the event must be read from the DB, then this method is useless.
Find by id
$research = ResearchModel::find(2);
Then you can run update function
$research->update([ 'name' => "test"]);
and if u don't want to use
ResearchModel::find(2);
then u have to use route binding
https://laravel.com/docs/6.x/routing#implicit-binding
Related
I have a model called CustomerInfo and i am trying to update it. update returns true but the changes are not reflecting on my db.
$customerInfo = CustomerInfo::where('machine_name',$username)->firstOrFail();
$result = $customerInfo->update($data);
$data varaible is a array having key value pair.
Also tried the following
$customerInfo = CustomerInfo::where('machine_name',$username)->update($data);
make sure $data variable that you want update record by its values, not be same with that record.
in this case, you don't have sql error but return of update will be zero.
Solved my questions.
Thanks Luciano.
i started eloquent manual db transaction and forgot to commit it at the end
DB::beginTransaction();//did this
$customerInfo = CustomerInfo::where('machine_name',$username)->firstOrFail();
$result = $customerInfo->update($data);
DB::Commit() //forgot to implement this part.
$result = $customerInfo->update($data);
$result variable will return only the boolean value. Try to return $customerInfo i.e.
return response()->json($customerInfo);
This will help you to find the actual problem and make sure the CustmerInfo model contains fillable properties and the $data variable contains all the information.
Try to use dd() like below to identify the issue:
dd($variable);
I used this query to update the status column.
$val="1";
vehicles::where('id' , '=' , $veh_status)->update(['status' => $val]);
But when I submitted the status value doesn't change.
you can trace your query by using ->toSql() method !
try this to find whats happening in back
Not sure what the problem is there because you haven't given much info to work with, but you can check these suggestions:
Check if the column is set to be mass assignable in the model class, that is, it is in the fillable[] array.
make sure the id you pass to the where() function is valid.
Try using another function, save() which will achieve the same results you seek, like this;
// filter the vehicle
$vehicle = vehicles::where('id', '=', $veh_id)->first();
or
$vehicle = vehicles::find($veh_id);
$vehicle->status = 1;
$vehicle->save();
Lastly, I noticed your id variable you pass to the where the () function is called $veh_status "presumably - vehicle status" and not $veh_id, "presumably - vehicle id" so probably check that out.
Ref: Laravel Model Update documentation
I have an Eloquent model on which I would like to increment a single attribute. So far I've been using the following line of code to achieve this:
Thread::where('id', $threadId)->increment('like_count');
This however has the unwanted side-effect of updating the updated_at timestamp. I've found the following way of updating a record without altering the timestamp:
$thread = Thread::where('id', $threadId)->first();
$thread->timestamps = false;
$thread->like_count++;
$thread->save();
But that suddenly looks a lot less concise. Therefore, I would like to know of there's a way to use the increment method without updating timestamps.
If you do not need timestamps at all, you can disable it once for all for that particular model using :
public $timestamps = false; inside your model. This will add additional step that whenever you want the timestamps to be updated, you need to assign them value manually like $object->created_at = Carbon::now()
Secondly, if you want those disabled for particular query, then as you mentioned in your question is one way.
Another way is using query builder. Now timestamps is the functionality associated with Eloquent. However, if you update using simple query builder, it does not update timestamps on its own.
So you can do :
DB::table('threads')
->where('id', $threadId)
->update([ 'votes' => DB::raw('votes + 1') ]);
However, I will personally prefer using Eloquent way of doing this if given a choice.
Update
You can now pass additional parameter to increment function to specify what other columns you would like to update.
So this will become :
$thread = Thread::find($threadId);
$thread->increment('votes', 1, [
'updated_at' => $thread->updated_at
]);
old thread but with laravel 7 and php7.4 you can do
Thread::where('id', $threadId)
->where(fn($q) => $q->getModel()->timestamps = false)
->increment('like_count');
older versions of php:
Thread::where('id', $threadId)
->where(function($q) {$q->getModel()->timestamps = false;})
->increment('like_count');
You could encapsulate the whole process into one method of the model.
I use Laravel as an API on an Angular app. One of the controllers has to update an array of objects.
This array, coming from Angular, might have
The same objects but with different attributes
One of the objects might have been deleted
New objects
So, I cannot just update the objects I have, since I need to delete the records that are not on the array any more and also create the new records.
At the moment, I have a not-so-nice solution to delete all the previous records and create new based on the array. Like this:
Sample::where('contest_id', $request->get('contest_id'))
->where('type', '0')
->delete();
$samples = $request->get('samples');
foreach ( $samples as $sample ) {
Sample::create($sample);
}
However, I want to add an activity logger to keep track of changes, but the above solution doesn't help. The activity logger works like this:
activity()
->causedBy($user)
->performedOn($sample)
->withProperties($properties)
->log('update'); //or new or delete
Where $properties is this:
$properties = [
'property' => [
'old' => $old_sample, // empty on creating new record
'new' => $sample // empty on deleting old record
],
];
Anything you could suggest?
Can't you have your frontend also send the sample_id when you need to update the records? If you're able to do that, you could play with Collections and make something like this:
// Retrieves all samples and turn them into a Collection
$samples = collect($request->get('samples'));
// Gets only the sample_ids that are not null and greater than zero
$changed_ids = $samples->pluck('sample_id')->filter()->all();
// These samples are new - create them
$new_samples = $samples->whereStrict('sample_id', null);
// These samples were changed - update them
$changed_samples = $samples->whereIn('sample_id', $changed_ids);
// These samples were deleted - remove them
$deleted_samples = Sample::whereNotIn('sample_id', $changed_ids);
Your solution seems like the most efficient, can you not retrieve the records to be deleted, log them as deleted and then actually delete them, then log the creation of the new ones?
In that scenario, your log is actually a better reflection of the activity that's occured.
I have the following eloquent code:
$gifts = FriendGift::find($collectedGifts); // An array of IDS
I want to set all as collected = 1.
I tried this:
$gifts->update(['collected' => 1]);
but I get the following error:
Method update does not exist
What's wrong?
You are not calling update on a Model. You are calling update on an Eloquent Collection which doesn't have a method update.
Just call the model and do a mass update like this:
FriendGift::whereIn('id', $collectedGifts)->update(['collected' => 1]);
If $collectedGifts is an Array, its not gonna work. Model::find() is waiting for a simple id, not an array.
Anyways, i prefer using the save method of an element if i want to update a field.
So you just get the Row you want, assign some value to it, and then save the instance.
For example:
$gifts = FriendGifts::find(15);//This is just 1 gift
$gifts->collected = 1;
$gifts->save();
For multiple gifts:
$gifts = FriedGifts::where('id',15)->get();
foreach($gifts as $one_gift){
$one_gift->collected = 1;
$one_gift->save();
}
Or something like that!
Hope this helps!
Good luck!