Laravel query updates multiple rows unexpectedly - laravel

In my web app I am trying to update one of many notes that are on one work order.
If I write query like this (Case 1):
// NOTE UPDATE WORKING FINE
Model::where('RN_key', $RN_key)->where('anNo', $anNo)->update(['acNote' => $request['note']]);
I get what I want, it's working fine - only one note on work order is updated as it should be.
If I write query update using first() and save() functions like this (Case 2):
// NOTE UPDATE NOT WORKING - Updates EVERY note on one work order but should update ONLY one
$getWorkSpecification = __vVX_ServisniNalog_Radovi::where('RN_key', $RN_key)->where('anNo', $anNo)->first();
$getWorkSpecification->acNote = $request['note'];
$getWorkSpecification->save();
Then it updates and overwrites every note on that same order thus every other note on order is lost. Why is that happening? I need to make it work with first() and save() functions because then it fires event so Laravel Auditing can save audit so I can have logs on every model change any user make.
With Case 1, every note updates fine but no audits are logged and thats the problem.

Related

How to display in blade which rows are soft deleted?

I have created a polling system and in the backend (CMS area) I want the ability for admins to be able to remove polls. When an admin removes a poll, it should soft delete the poll. This is working as intended, however I also want to have the ability for the admin to be able to restore a poll. To do this I am displaying all of the polls (including the soft deleted polls) in the admin area.
PollController index() to get all polls
$polls = Poll::withTrashed()->get();
In the blade I want to have two different buttons for each poll. One of restoring and one for deleting but I only want to display 1 button for each poll depending on whether it can be restored or deleted.
To do this, I have put this inside the foreach in the blade:
#if($poll->trashed())
// Restore button
#else
// Delete button
#endif
However the issue is, trashed() keeps returning true for all the polls when only 1 out of the 3 polls I have are actually soft deleted. I am unsure as to why trashed() returns all of these are true?
How would I get this method working correctly? Thanks.
PART 1
It depends on your query. When using soft deletes, Laravel will query all models that are not soft-deleted by default. When you also want to get the soft-deleted models, you need to call the withTrashed() method on your query. Read more here:
https://laravel.com/docs/5.5/eloquent#querying-soft-deleted-models
To understand what withTrashed() does, you need to understand how soft-deleting works. Soft-deleting models works by adding a new column to your database tables called deleted_at. It's value defaults to null. When you soft-delete a model, Laravel will put the current timestamp into that column. Therefore, this field doesn't contain a null value anymore.
When querying models when using soft-deletes, Laravel appends a deleted_at is null condition to the query. Calling the withTrashed() method, removes that condition from the query.
Have a look on the source of the default query modifier and the withTrashed method.
PART 2
That are events. You can call that to tell Laravel, that it should execute that specific closure when this event happens. In your example, it is listening for the "deleting" event. See more on that here:
https://laravel.com/docs/5.5/eloquent#events
PART 3
You can entirely delete soft-deletable models with the forceDelete() method. See "Permanently Deleting Models" here:
https://laravel.com/docs/5.5/eloquent#querying-soft-deleted-models
FOR EXAMPLE
$items = App\Model::withTrashed()->get();
If you want to restore a single item, just find it by ID:
$item = App\Model::find($id);

Why Laravel/Eloquent single object save() updates multiple records

I'm fetching a specific record with a DB table using
$myTableObj = MyTable::where(['type' => $sometype])->first();
Getting it successfully, updating some fields and saving with
$myTableObj->save();
Surprisingly, this record is updated along with another record that also has 'type' = $sometype. What can be done to prevent this?
NOTE: originally the table did not have the auto increment id field, but I have read in forums that it may make problems in Laravel so I did add it, which did not solve the problem.
Method save() working with 'id' filed only.
You can try this
$myTableObj = MyTable::where(['type' => $sometype])->update(['something' => 'value']);
Source
I understand update() is to update, but, my answer works fine and fits good for update too. Its useful where you dont want columns to be defined once again for update, (sp when they are not fillable, its tested with primary key as condition)
$myTableObj->save(); basically its for saving new record, if you want to update that row you can update like below code:
$myTableObj=new MyTable;
$myTableObj->exists=true;
$myTableObj->type=$sometype;//this is your condition, identify
$myTableObj->update();
I think what's happening here is Laravel is saving as well as updating row.

Algolia Update Index On Relational Database change with Laravel Scout

I have implemented Aloglia for my Movies table with actors as relational table and it works fine.
Problem:
When I update any movie its also updating algolia index (its good). But how can I update index if I made any change in relational table (for example update an actor of movie).
How to push a specific record manually with laravel scout.
Thanks
The issue itself lies in laravel's events. Whats happening is scout is listening for an 'updated' event which only occurs in laravel when the model object is saved and is dirty (aka value differ from that in the db).
There are two ways you can do this.
The bad lazy way would simply be to add ->touch() to the model prior to save - this will force the updated_at field to update and ultimately trigger the updated event. This is bad as you're wasting a DB query.
The second and preferable way is to register another observer on 'saved' which triggers regardless of whether or not the object is dirty. Likely you either want to check if the model is dirty and only index when its not (to prevent double indexing from the updated event) or just de-register the 'updated' listener that comes in Scout.

RethinkDb changefeeds not working when including `.pluck`

I have a changefeed that works fine until I use the pluck() projection. If I use pluck, it doesn't pick up changes form inserts and deletes in my followers embedded collection.
r.table('users')
.getAll(name, {index: 'followers'})
//.without('password', 'phone')
.pluck('name', 'online') // using pluck doesn't pick up changes in insert/delete from followers
.changes({includeInitial:true});
I could use the without command but that seems more error prone as I would have to keep updating that list anytime I added fields to the user object.
Updates to user's online property gets picked up in the changefeed in either scenario.
Why does pluck not show changes to the followers set/collection property?
I'm not 100% sure, but I think this is because when you add the .pluck('name', 'online') to the end, and then you update the followers array, the changefeed logic applies the pluck and then compares the old value to the new value, and since neither of the plucked fields changed it decides that it's a "trivial" change and drops it. (In general ignoring trivial changes is what you want, since one of the main goals of .pluck.changes is to only be notified when the specified fields change.)
I think this probably isn't the desired behavior, though: it's probably more useful to only drop trivial changes if they don't cause the row to enter or exit the subscribed range. I opened https://github.com/rethinkdb/rethinkdb/issues/5205 to track that change.
This isn't supported right now. Check this ticket and this.

ObjectStateManager vs ApplyCurrentValues when updating an entity?

I know that using ObjectStateManager just results in 1 trip to the database, but a larger update statement and ApplyCurrentValues results in 2 trips to the database, one to retreive the entity and one to update it, so what are the pros and cons of each also, how does issuing the following statement know that I want to update that current record, I know it has something to do with loading it into context, but not sure how it works.
[HttpPost]
public ActionResult Edit(Movie movie)
{
(from m in _db.Movies1
where m.Id == movie.id
select m).First()
//How does calling the above query know to update the movie,
can't I do it with out it?
_db.Movies1.ApplyCurrentValues(movie);
_db.SaveChanges();
}
The code you posted 'knows' you want to update the record because it assumes if the state is modified (which applycurrentvalues will mark properties as modified) then you must want to update that field.
So anything that is modified is set, and then sent to the database. However the code that has .First() in it does nothing helpful here.
ApplyCurrentValues does not load anything, so your first line of code loads it into the context. Then you ApplyCurrentValues merges the values into it. Anything that is different is marked as modified and copied over then those fields only are sent to the db for update.
You can profile the activity, check out
http://msdn.microsoft.com/en-us/magazine/gg490349.aspx
also there is a nice demp profiler available at http://efprof.com/
Another option is to simply attach as modified and save changes. I think that will only yield one query (the update to the database), I'll have to double check that.
That code would look like:
_db.Entry(movie).State = EntityState.Modified; //attaches is as well
_db.SaveChanges();
That will save every property, but I think it may be one less trip (update, reload, as opposed to load, update, reload)

Resources