StreetCoder
StreetCoder

Reputation: 10061

How events work in Yii2

I have been trying to learn how event works in Yii from the Yii Guide. I have found there are most important things: Event Handlers, Attaching Event Handlers and Triggering Events. I have read entire the article properly. But I don't understand how to implement these three things properly. How to see the effect of it's implementation. I have extended component class as:

namespace app\components;

use yii\base\Component;
use yii\base\Event;
use yii\web\View;

class Foo extends Component{

   const EVENT_HELLO = 'hello';

   public function bar()
   {
      $this->trigger(self::EVENT_HELLO);
   }

}

I do not understand what is the next part to do. Where I should write the Attaching Event Handlers. Can you help me someone, at least I can see a simple output using event.

Upvotes: 2

Views: 5710

Answers (1)

vitalik_74
vitalik_74

Reputation: 4591

You may create init() method in model:

public function init()
    {
        $this->on(Event::ACTION_ADD, ['app\models\Event', 'sendInLog']);
        $this->on(Event::ACTION_DELETE, ['app\models\Event', 'sendInLog']);
        $this->on(Event::ACTION_UPDATE, ['app\models\Event', 'sendInLog']);
    }

In initialize events in second parameter you may use current model or set other model. If you want use current model set like that:

[$this, 'sendInLog']

sendInLog it is method in model. In method sendInLog one parameter it is $event. This is object \yii\base\Event. In property $event->name - it is event name. In property $event->sender - it is model class from trigger event.

In my class app\models\Event like that:

namespace app\models;

class Event extends Component
{
    const ACTION_ADD = 1;
    const ACTION_DELETE = 2;
    const ACTION_UPDATE = 3;

    const TYPE_PROJECT = 10;
    const TYPE_BIDS = 20;
    const TYPE_BIDS_DATA = 30;

    /**
     * @param $event
     */
    public static function sendInLog($event)
    {
        /** @var \yii\base\Event $event */
        /** @var ActiveRecord $event->sender */
        $userId = Yii::$app->user->id;
        $model = new Logs([
            'type' => $event->sender->getType(),
            'action' => $event->name,
            'id_user' => $userId,
            'old_data' => Json::encode($event->sender->attributes),
            'new_data' => Json::encode($event->sender->oldAttributes),
        ]);
        $model->save();
    }
}

Run trigger like that:

public function afterDelete()
    {
        $this->trigger(Event::ACTION_DELETE);
        parent::afterDelete();
    }

Or

public function actionView()
    {
        $this->trigger(Event::ACTION_VIEW);
        $this->render(...);
    }

EDIT:

For example. If you want run trigger after delete, insert, update. You may use trigger in afterDelete, afterSave in model. If you want run trigger in controller run trigger like that:

public function actionCreate()
    {
        $model = new Bids();
        $model->id_project = Yii::$app->request->get('projectId');
        $fieldsDefaults = BidsFieldsDefaults::find()->orderBy(['order' => SORT_ASC])->all();

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            $model->trigger(Event::ACTION_ADD);
            return $this->redirect(['view', 'id' => $model->id]);
        } else {
            return $this->render('create', [
                'model' => $model,
                'fieldsDefaults' => $fieldsDefaults
            ]);
        }
    }

I show you two different ways to run trigger. Which one to use is up to you :)

Upvotes: 12

Related Questions