wasChanged() vs wasRecentlyCreated - Laravel Tips
Tony Joe Dev
Posted on January 2, 2024
Let's start with a simple model like this:
class MyModel extends Model
{
protected $fillable = [
'name'
];
protected static function booted(): void
{
static::created(function ($model) {
$model->dumpEvent('CREATED');
});
static::updated(function ($model) {
$model->dumpEvent('UPDATED');
});
static::saved(function ($model) {
$model->dumpEvent('SAVED');
});
}
public function dumpEvent(string $event): void
{
dump([
'event' => $event,
'wasChanged()' => $this->wasChanged(),
'wasRecentlyCreated' => $this->wasRecentlyCreated
]);
}
}
Let’s create a new model:
$model = MyModel::create(['name' => 'ABC']);
We get:
array:3 [ // app/Models/MyModel.php:30
"event" => "CREATED"
"wasChanged()" => false // <-- ❗
"wasRecentlyCreated" => true
]
array:3 [ // app/Models/MyModel.php:30
"event" => "SAVED"
"wasChanged()" => false // <-- ❗
"wasRecentlyCreated" => true
]
NOTE:
- ❗
wasChanged()
isfalse
If we call save()
without changes on the same model instance:
// $model = MyModel::create(['name' => 'ABC']);
// ...
// ... no changes on `$model` fields
$model->save();
We get:
array:3 [ // app/Models/MyModel.php:30
"event" => "SAVED"
"wasChanged()" => false
"wasRecentlyCreated" => true
]
NOTE:
- it will be triggered the
saved()
event - but it will not be triggered the
updated()
event -
wasRecentlyCreated
is stilltrue
(remember: it’s the same$model
instance)
Now, let’s make some changes, always on the same model instance:
// $model = MyModel::create(['name' => 'ABC']);
// ...
$model->name = 'ABC new';
$model->save();
We get:
array:3 [ // app/Models/MyModel.php:30
"event" => "UPDATED"
"wasChanged()" => true
"wasRecentlyCreated" => true // <-- ❗
]
array:3 [ // app/Models/MyModel.php:30
"event" => "SAVED"
"wasChanged()" => true
"wasRecentlyCreated" => true // <-- ❗
]
NOTE:
-
wasChanged()
istrue
(OK, we expected it to be) - ❗
wasRecentlyCreated
is stilltrue
(remember: it’s the same$model
instance)
What happens after a refresh()
?
// $model = MyModel::create(['name' => 'ABC']);
// ...
// $model->name = 'ABC new';
// $model->save();
$model->refresh();
$model->save();
We get again:
array:3 [ // app/Models/MyModel.php:30
"event" => "SAVED"
"wasChanged()" => true // <-- ❗
"wasRecentlyCreated" => true // <-- ❗
]
So even after a refresh()
, it doesn’t change the internal status for the wasChanged()
or wasRecentlyCreated
!
Conclusion
In general, between different requests, reloading a model from the DB does not generate problems. But the behavior of wasChanged()
and wasRecentlyCreated
can become bizarre in the same request, i.e. on the same instance of the newly created model, especially if the model is configured to trigger events in the saved()
method, when something has actually changed, for example:
protected static function booted(): void
{
static::saved(function ($model) {
if (! $model->wasChanged() && ! $model->wasRecentlyCreated) {
return; // no changes and no new record
}
event(new MyCustomEvent(
$model->wasRecentlyCreated ? 'mymodel.new' : 'mymodel.updated'),
$model
);
});
}
✸ Enjoy your coding!
If you liked this post, don't forget to add your Follow to my profile!
If you want to preview my content, Subscrive to my Newsletter!
Posted on January 2, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.