-
Notifications
You must be signed in to change notification settings - Fork 10.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Observers: updated triggers itself with an update and getDirty retains the previous updated field #27138
Comments
This is happening because the |
Well, think about it. The "updated" event happens after your model was updated. So any changes you made on your model are bound to still be picked up by the Anyway, this is more of a question for one of the below support channels. If you can actually identify this as a bug, feel free to report back. |
I know OP didn't say "how to I make this not happen", but those responses are trash. The solution to this issue is to use $model->unsetEventDispatcher() before the update inside the observer. |
I have just come across the same issue. In case it helps anyone else, my problem was calling public function updating(Model $model)
{
if ($model->isDirty('some_attribute')) {
if ($model->some_attribute == 'this_value') {
$model->update(['some_other_attr' => 'another_value']);
}
}
} The solution is to simply call |
Changing the value without even updating or saving will reflect on model in db. |
Description:
I don't know if this is a bug or expected behaviour, we've been looking at this with 3 devs and no one could provide a proper answer.
I have an UserObserver and every time a user gets updated and the active field updates to true a new password is generated and a welcome email is sent.
The function looks like this.
As you can see in the if statement there is a check to see if the user is active and if the database field has been changed (isDirty()). If this is true a new password is being generated, hashed with bcrypt, stored and then send to the user via notifications. (mail)
As expected the password update triggers the observer method again, but now the isDirty('active) should return false. This does not happen, it returns true through all the iterations. This goes on until PHP timeouts or xdebug throws an exception that the nesting level of 256 is reached.
Why does
$user->isDirty('active')
return true throughout every update in this loop although the last update in the observer did not update the active field?When I call
$user->getDirty()
returns this the first time the updated method is triggered.From the second time it returns until the timeout is reached:
I've taken a look at
Illuminate\Database\Concerns\HasAttributes
there I have tried to backtrace what happens exactly withgetDirty
,isDirty
,wasChanged
andisChanged
. Although this gave great insights I can not find the source of this behaviour. Can someone explain why the updated fields from the previous iterations are present until the timeout is reached? My guess goes to the fact that the whole process has one call stack and$this->attributes
only gets empty a successful return or in this example PHP that cuts the process because of a timeout.Steps To Reproduce:
isDirty('first_field_name')
isDirty('first_field_name')
still returns truegetDirty()
returns the first_field_name on all itterationsThe text was updated successfully, but these errors were encountered: