I want to run an action after any model got deleted, but currently it seems like I do something wrong.. I already get the Model before I delete it, so the event should get fired.
As I do already some general handling in my AppServiceProvider and it's only a small piece of code I want to handle the Event direct in the Provider.
simplified AppServiceProvider.php
<?php
namespace App\Providers;
use App\Models\DebugLog;
use App\Models\Jobs\JobLog;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Event;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Event::listen('eloquent.deleted: *', function(string $eventName, array $data){
DebugLog::create([
'function' => 'AppServiceProvider: Event eloquent.deleted',
'object' => json_encode($data,JSON_PRETTY_PRINT),
'message' => $eventName
]);
//JobLog::where('tablename',$c_table)->where('entryid',$c_id)->delete();
});
}
}
The Model get deleted like this
$deletionSucc = InboundPlan::where('inboundplanid',$container->inboundplanid)->where('account',$container->__get('account'))->first()->delete();
So normally the event should get fired that way and the listener looks pretty much like here: https://laravel.com/docs/11.x/events#wildcard-event-listeners
Laravel logfile doesn't show any error, too. May do I the whole listening wrong? That's why I wrote the title like it is.
EDIT (my solution):
I decided to use a Trait for this case, because in the end NOT EVERY Model should trigger the code. In the beginning I just don't want to add code to every related Model. The Trait looks like this:
JobLogDeletionTrait.php
<?php
namespace App\Traits;
use App\Models\DebugLog;
use App\Models\Jobs\JobLog;
trait JobLogDeletionTrait
{
public static function bootJobLogDeletionTrait()
{
static::deleting(function ($model) {
$modelArr = $model->toArray();
$succ = JobLog::where('tablename',$model->getTable())->where('entryid',$modelArr[$model->getKeyName()])->delete();
});
static::deleted(function ($model) {
$modelArr = $model->toArray();
$succ = JobLog::where('tablename',$model->getTable())->where('entryid',$modelArr[$model->getKeyName()])->delete();
});
}
}
Inside the related Model you only need to use the Trait, what is imo a cleaner way as to listen to every model deletion event. This link helped me at the decision making: https://satyanveshak.com/articles/handle-events-for-eloquent-models-in-laravel/#3-alternative-using-traits
You can use directly Model
to listen the events in AppServiceProvider
.
for example:
// Listen for the "deleting" event on all models
Model::deleting(function ($model) {
Log::info('A model is about to be deleted:', [
'model' => get_class($model),
'attributes' => $model->toArray(),
]);
});
// Listen for the "deleted" event on all models
Model::deleted(function ($model) {
Log::info('A model has been deleted:', [
'model' => get_class($model),
'attributes' => $model->toArray(),
]);
});
You just need to take care of actions based on Model class and which models to be excluded.
this might help Listen Events on all elequent models globally