用雄辩的方式监听父模型上的事件

时间:2016-03-04 13:12:11

标签: laravel eloquent

我的所有模特都有普通课。

class Base扩展Model;

A类扩展Base;

B类扩展Base;

我可以在每个模型saving上听A::saving(callback()但是它似乎无法在Base上听。 Base::saving(callback)

<?php


class BaseModel extends \Illuminate\Database\Eloquent\Model
{


}


class A extends BaseModel
{
    protected $table = 'a';
}

class B extends BaseModel
{

    protected $table = 'b';
}


class BusinessLogicProvider extends \Illuminate\Support\ServiceProvider
{

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        A::updating(function () {
            //this fires
        });

        BaseModel::updating(function(){
            //this never fires
        });
    }
}

2 个答案:

答案 0 :(得分:0)

它不适用于继承,因为事件系统不能以这种方式工作。注册模型事件侦听器时,它只侦听该模型,但不侦听它的扩展名。

\Illuminate\Database\Eloquent\Model第1281行:

protected static function registerModelEvent($event, $callback, $priority = 0)
{
    if (isset(static::$dispatcher)) {
        $name = get_called_class();
        static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback, $priority);
    }
}

https://github.com/laravel/framework/blob/5.2/src/Illuminate/Database/Eloquent/Model.php#L1281

答案 1 :(得分:0)

我想出了一个具有forward_static_call()功能的解决方案:

        $classes = [
            \App\Models\XinFinance\ExcilerSource::class,
            \App\Models\XinFinance\ExcilerVersion::class,
            \App\Models\XinFinance\ExcilerDict::class,
            \App\Models\XinFinance\ExcilerCell::class,
        ];

        foreach ($classes as $class) {
            forward_static_call(
                [$class, 'saving'],
                function ($model) {
                    // your logic...
                });
        };

显然这并不理想,因为您必须手动添加子类。但这是我现在可以想到的最好方法。希望其他人能想出一种更明智的方法。

更新

我碰到了这篇文章https://laracasts.com/discuss/channels/eloquent/listen-to-any-saveupdatecreate-event-for-any-model,所以有一种更好的方法:

在您的BaseModel中:

    public static function boot()
    {
        static::saving(function () { // your logic... } );
        parent::boot();
    }