laravel Eloquent model update event is not fired
Solution 1
You need to retrieve the user from the database and then save that user in order to fire the event. For example:
This will NOT fire the update event:
User::where('id', $id)->update(['username' => $newUsername]);
This will fire the update event:
User::find($id)->update(['username' => $newUsername]);
Solution 2
Possible reasons:
The row is not updated at all - no changes. Hence not firing, and
You used
update
. Check the docs here: https://laravel.com/docs/5.3/eloquent#updates
When issuing a mass update via Eloquent, the saved and updated model events will not be fired for the updated models. This is because the models are never actually retrieved when issuing a mass update.
northblue
Updated on July 09, 2022Comments
-
northblue almost 2 years
Merry Christmas guys!
I am new to Laravel. Just had a beginner's question, when I am trying to use service provider and model event to log the update information.
Was following the online doc: https://laravel.com/docs/5.3/eloquent#events
After put all code together, I find that the model event only fire when create the use but never log anything when I edit the user.
Did I miss anything? Feel like the $user didn't get assigned properly. Where is it from? from other service provider?
Any explanation or hint will be appreciated!
<?php namespace App\Providers; use App\User; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return void */ public function boot() { User::creating(function ($user) { Log::info('event creating'); }); User::created(function ($user) { Log::info('event created'); }); User::updating(function ($user) { Log::info('event updating'); }); User::updated(function ($user) { Log::info('event updated'); }); User::saving(function ($user) { Log::info('event saving'); }); User::saved(function ($user) { Log::info('event saved'); }); User::deleting(function ($user) { Log::info('event deleting'); }); User::deleted(function ($user) { Log::info('event deleted'); }); } /** * Register the service provider. * * @return void */ public function register() { // } }
-
Lionel Chan over 7 yearsWhat's your code that does the
create
andedit
? It could be that no changes were made hence the event was not fired, or you are doing mass updating which is not firing event at all. -
northblue over 7 yearsThanks @LionelChan, Ohgodwhy and Eric Tucker! The event trigger is working perfectly after change the update to: User::find($id)->update(['username' => $newUsername]); Appreciated for your help!
-
Lionel Chan over 7 yearsSame goes to
delete
. Model will fire relevant events only when model object is being created. Which means it only fires if you dofind
,get
,first
first to retrieve the objects :)
-
-
Ohgodwhy over 7 yearsIn short; you must issue a
find($id)
and modify the properties manually for this to work correctly. -
padawanTony almost 4 yearsThis works:
User::find(4)->update(['earings' => 0]);
while this doesn't:$user = User::find(1); $user->earings=0; $user->update()
. In the second case the event is not being fired. Can you explain why? What is the difference between the two statements? Aren't they both mass assignment? -
padawanTony almost 4 yearsThis works:
User::find(4)->update(['earings' => 0]);
while this doesn't:$user = User::find(1); $user->earings=0; $user->update()
. In the second case the event is not being fired. Can you explain why? What is the difference between the two statements? Aren't they both mass assignment? -
Eric Tucker almost 4 yearsBoth of your examples are doing the same thing and will fire the event only if the model is dirty. In your case, the model event will only fire if
$user->earings
does not equal0
. This may be what you are experiencing. -
padawanTony almost 4 yearsYou mean if the original value of earings was not 0. It wasn't. This is why I'm doing
$user->earings=0;
. So that it changes and the instance becomes dirty. -
padawanTony almost 4 yearsOK. I'm reading the source code trying to understand this. The question I have now is this, "How does changing an attribute (ex:
$user->earings=0;
) make the instance dirty? Which is the code/function that does that? -
Eric Tucker almost 4 yearsWhen Laravel pulls a model from the database it immediately stores a snapshot of the original state. Then, when you update attributes, before persisting those changes to the DB, Laravel checks the current state of each attribute against what was pulled originally from the database. When at least one of those don't match, that model is considered dirty and only then will the actual update command be sent to the DB and events will be fired.
-
Grant over 2 yearsUm... why though? Had to change my where to find & it fixed my event misfire... thanks
-
Eric Tucker over 2 years@Grant It's because, in this case, model events are registered for each model when they're hydrated from the database. These are not database triggers. Without pulling the row from the db, ie:
User::where('id', $id)->update(['username' => $newUsername]);
, you're just executingUPDATE users SET username = ? WHERE id = ?
which never hydrates a model, bypassing those events. -
Grant over 2 yearsThanks for the answer @EricTucker makes perfect sense