2

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.

StreetCoder
  • 9,103
  • 7
  • 36
  • 55
  • Here is detail answer about events: http://stackoverflow.com/questions/28575636/how-to-use-events-in-yii2/28586567#28586567 – Ejaz Karim Apr 11 '16 at 15:35

1 Answers1

12

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 :)

vitalik_74
  • 4,383
  • 2
  • 15
  • 25
  • Thanks it's a nice example, let me check it and try :) – StreetCoder Mar 25 '15 at 17:52
  • Can you tell me please about `afterDelete()` and `actionView()`. They will be in the model? – StreetCoder Mar 25 '15 at 17:57
  • just one thing, can you tell me about `$model = new Logs` please. Because I am getting an error, `app\models\Logs`. – StreetCoder Mar 25 '15 at 18:18
  • I got the concept now. So far I understand Logs is `model`. After event trigger, a log data will be stored in database. I have created a `Logs` model but when I trigger event `ACTION_ADD`, `\yii\base\Event::sendInLog` does not save the data in db. – StreetCoder Mar 25 '15 at 19:27
  • You wrong is `\yii\base\Event`. I create new class `app\models\Event` (he code in my answer). This class a example how work with trigger. – vitalik_74 Mar 26 '15 at 06:34
  • Sorry mentioned wrong in the above comment. I wrote class in `app\models\Event`. However, it works fine here when I want to echo any text. But I can't save logs data in database while trigger. Anyway, I want to give you a lot of thanks for your big help. – StreetCoder Mar 26 '15 at 14:31
  • I saw event handler can be attach in component section of config file using the syntex `'on eventName' => $eventHandler,`. Can I do it for this example? – StreetCoder Mar 26 '15 at 14:34