Yii2:我可以附加模型类之外的事件吗?

时间:2018-06-22 10:33:24

标签: php events yii2

我目前正在编写一个为选择字段缓存模型数据的类。 现在很明显,如果插入,更新或删除了影响此选择字段的任何模型,则必须刷新缓存。

要处理此问题,我想使用Yii2的模型事件。例如,如果在模型Album中触发了EVENT_AFTER_INSERT,则我想执行代码以刷新专辑选择数据的缓存。

现在,我可以按照经典方式进行操作,并向模型Album添加一个事件,如下所示:

class Album extends ActiveRecord {

    public function init(){
      $this->on(self::EVENT_AFTER_INSERT, [$this, 'refresh_cache']);
      $this->on(self::EVENT_AFTER_UPDATE, [$this, 'refresh_cache']);
      $this->on(self::EVENT_AFTER_DELETE, [$this, 'refresh_cache']);
    }

    // ...

}

可以,是的。问题是,我需要在任何要从开发的任何点创建选择字段的模型中都包含此代码。没什么大不了的,但是您可以在编码时轻松地忘记它,如果行为需要在某个时候改变,则需要更新一大堆模型。

现在这是我的问题:是否有可能从另一个组件向模型添加事件?我的想法是创建一个组件,该组件了解所有使用的选择数据缓存并相应地添加必要的模型事件。知道如何实现这一目标或类似目标吗?

3 个答案:

答案 0 :(得分:1)

  

您只需要创建一个行为并将其附加到您的各种模型即可。参见basic guide,尤其是Behavior::events()用例

所以我继续写一个例子

class RefreshCacheBehavior extends \yii\base\Behavior
{

    public function events() {
        return [
            \yii\db\ActiveRecord::EVENT_AFTER_INSERT => 'refreshCache',
            \yii\db\ActiveRecord::EVENT_AFTER_UPDATE => 'refreshCache',
            \yii\db\ActiveRecord::EVENT_AFTER_DELETE => 'refreshCache',
        ];
    }

    /**
     * event handler
     * @param \yii\base\Event $event
     */
    public function refreshCache($event) {
        // model that triggered the event will be $this->owner
        // do things with Yii::$app->cache
    }

}


class Album extends ActiveRecord {

    public function behaviors() {
        return [
            ['class' => RefreshCacheBehavior::className()],
        ];
    }
// ...

}

答案 1 :(得分:1)

  

是否有可能从另一个组件向模型添加事件?

是的!您可以使用class level event handlers。下面的代码行显示了如何执行此操作。

Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
    Yii::debug(get_class($event->sender) . ' is inserted');
});

您可以在init方法中使用相同的代码,并将其绑定到您的类方法而不是该闭包中。

我将创建一个实现BootstrapInterface的类并将其添加到config中。然后我将在那里处理那些类级别的事件!

帮个忙,阅读the Guidethe API Documentation中的事件

答案 2 :(得分:0)

on()是公共方法,因此您始终可以将事件附加到已实例化的对象。如果您使用某种工厂来构建对象,这可能会很有用:

public function createModel($id) {
    $model = Album::findOne($id);
    if ($model === null) {
        // some magic
    }

    $model->on(Album::EVENT_AFTER_INSERT, [$this, 'refresh_cache']);
    $model->on(Album::EVENT_AFTER_UPDATE, [$this, 'refresh_cache']);
    $model->on(Album::EVENT_AFTER_DELETE, [$this, 'refresh_cache']);

    return $model;
}