astroame
astroame

Reputation: 399

Laravel : one observer for multiple models

I have multiple model that have same logic oncreated method, can I have one observer for that? Or another approach just to avoid creating multiple Observers for each model?

Upvotes: 4

Views: 4865

Answers (5)

Lloric Garcia
Lloric Garcia

Reputation: 49

This is much better when you apply this in provider, so in the future you can easily remove if laravel provide a better way.

currently we using laravel v8.42.1, but this seems applicable in older version.


namespace App\Providers;

use App\Observers\GlobalObserver;
use App\Models\Product;

class ObserverServiceProvider extends ServiceProvider
{
    public function register()
    {
        //
    }

    public function boot()
    {
        self::registerGlobalObserver();
    }

    private static function registerGlobalObserver()
    {
        /** @var \Illuminate\Database\Eloquent\Model[] $MODELS */
        $MODELS = [
            Product::class,
            // ...... more models here
        ];

        foreach ($MODELS as $MODEL) {
            $MODEL::observe(GlobalObserver::class);
        }
    }
}

Then this will be your observer

<?php

namespace App\Observers;

use Illuminate\Database\Eloquent\Model;

class GlobalObserver
{
    public function updated(Model $model)
    {
        // ...
    }

    public function created(Model $model)
    {
        // ...
    }

    public function deleted(Model $model)
    {
        // ...
    }

    public function forceDeleted(Model $model)
    {
       // ...
    }
}

Then register the provider in config/app.php in providers key

    'providers' => [
        \App\Providers\ObserverServiceProvider::class,
        // ...
    ],

the good this about this is you never go to the multiple model class just to modify them

Upvotes: 4

Denis Duli&#231;i
Denis Duli&#231;i

Reputation: 1

You can use the Observer class for that purpose https://laravel.com/docs/6.x/eloquent#observers

Upvotes: 0

Foued MOUSSI
Foued MOUSSI

Reputation: 4813

You may register Closure based events manually in the boot method of your EventServiceProvider:

/**
 * Register any other events for your application.
 *
 * @return void
 */
public function boot()
{
    parent::boot();

    Event::listen(['eloquent.saved: *', 'eloquent.created: *', ...], function($context) {
       // dump($context); ---> $context hold information about concerned model and fired event : e.g "eloquent.created: App\User"
       // YOUR CODE GOES HERE
    });
}

Upvotes: 3

Elias Soares
Elias Soares

Reputation: 10254

You can use a bootable trait for this purpose.

<?php
namespace App\Traits;

trait MyModelTrait
{
    public static function bootMyModelTrait()
    {
        static::created(function ($model) {
            $model->someField = 'someLogicValue';
        });
    }
}

Upvotes: 9

mdexp
mdexp

Reputation: 3567

I would keep an observer per model, but instead extract a Trait/a base class/a service class with the common functionality that you can then use in those observers.

Upvotes: 1

Related Questions