I am building a package that logs changes that happen on eloquent and I'm trying to figure out what to check to ignore the updated
event when restored
.
trait HasLogs
{
public static function bootHasLogs(): void
{
// created ...
self::updated(callback: fn ($model) => self::log($model, 'updated'));
self::deleted(callback: function ($model) {
// Ignore 'deleted' event when 'softDeleted' or 'forceDeleted'
if (in_array('Illuminate\Database\Eloquent\SoftDeletes', (class_uses(self::class)))) {
return;
}
self::log($model, 'deleted');
});
if (in_array('Illuminate\Database\Eloquent\SoftDeletes', (class_uses(self::class)))) {
// softDeleted ...
self::restored(callback: fn ($model) => self::log($model, 'restored'));
// forceDeleted ...
}
}
// ...
}
Here is the actions order if that helps:
Model::restore()
on the SoftDeletes
trait.restoring
is fired.Model::save()
saving
is fired.Model::performUpdate()
updating
is fired.Builder::update()
updated
is fired.Model::finishSave()
saved
is fired.restored
is fired.The trait HasLogs
adds a Boolean attribute to the Model
named loggableIsBeingRestored
set to false
by default.
The trait also registers a new listener for restoring
which sets loggableIsBeingRestored
to true
at the begging of the described actions.
Then the updated
listener checks for loggableIsBeingRestored
before proceeding with its actions.
trait HasLogs
{
public bool $loggableIsBeingRestored = false;
public static function bootHasLogs(): void
{
// ...
self::updated(callback: function ($model) {
if (isset($model->loggableIsBeingRestored) && $model->loggableIsBeingRestored) {
// This is a restored event so don't log!
return;
}
self::log($model, 'updated');
});
// ...
self::restored(callback: function ($model) {
self::log($model, 'restored');
$model->loggableIsBeingRestored = false;
});
self::restoring(callback: function ($model) {
$model->loggableIsBeingRestored = true;
});
}
// ...
}