Lejiend
Lejiend

Reputation: 1299

How to implement eloquent 'saving' event for all models , not individually

Based on documentation of laravel eloquent event, all the eloquent event are triggered individually based on each model, is there any way to use 'creating' event or any other eloquent event to be triggered by all the Models

For example , if any Models is created , event A is triggered

Upvotes: 1

Views: 5075

Answers (3)

Phil Tune
Phil Tune

Reputation: 3305

You might find yourself having a good use-case for creating a trait instead of extending Illuminate\Database\Eloquent\Model. Consider:

<?php

namespace App\Models\Traits;

trait UpdatesUser
{
    public static function bootUpdatesUser()
    {
        static::saving(function(self $model) {
            Auth::user()->update([
                'changed_on' => now(),
                'changed_by' => $model->id,
                'changed_by_class' => $model::class
            ]);
        });
        static::updating(function(self $model) {
            if ( $model->isDirty() ) {
                Auth::user()->update([
                    'changed_on' => now(),
                    'changed_by' => $model->id,
                    'changed_by_class' => $model::class
                ]);
            }
        });
    }
}

The boot{TraitName} method will boot every time the model gets loaded, which means you won't have to overwrite and call parent::boot() on the model. I personally am using this pattern to mark changes to any children of a parent model.

<?php

namespace App\Models;

use App\Models\Traits\UpdatesUser;
use Illuminate\Database\Eloquent\Model;

class ChildModel extends Model
{
    use UpdatesUser;
    ...
}

// Both of these will update my `users` table, notifying me a change has been made.

ChildModel::create([...]);

ChildModel::find(1)->update([...]);

Upvotes: 0

SteD
SteD

Reputation: 14027

Extend the model class:

use Auth;
use Illuminate\Database\Eloquent\Model;

class GeneralModel extends Model
{
  public static function boot()
  {
    parent::boot();

    static::creating(function ($model) {
        if (Auth::user()) {
            $model->created_by = Auth::user()->id;
            $model->updated_by = Auth::user()->id;
        }
    });
  }
}

When you say create a say property object, it will be triggered. Use it for all the models you need this.

class Property extends GeneralModel
{
  //..
}

Upvotes: 5

lagbox
lagbox

Reputation: 50481

Listen for the Eloquent creating event that is fired. It is a 'string' event still not an object so you can do some ... wildcard matching here.

This is the string of the events that are fired from Eloquent:

"eloquent.{$event}: ".static::class

So you could listen for "eloquent.creating: *" to catch all those string events for Eloquent creating for any Model.

Event::listen('eloquent.creating: *', function ($event, $model) {
    ....
});

Obviously if you have defined your model to use custom event objects this would not be able to catch those.

You also could make a model observer, but you would have to register it to every model in your application you wanted to catch events for.

Upvotes: 3

Related Questions