How to inject Events and Behaviors to a Model?

Hello.

In our system we have “abstract class Document extends ActiveRecord” and we need all child classes to react on EVENT_AFTER_UPDATE.

This is why I created a behavior that contains the afterUpdateHandler() function.

Now I need to use DI to inject this behavior to the abstract class (so all children can use it) and attach its function afterUpdateHandler() to the AR event EVENT_AFTER_UPDATE

Important is to know this all is in a module. So I added method init() to the file Module.php, but the behavior is not injected. I probably have something wrong.

I am doing it like this:

        Yii::$container->set(Document::class, [
            'as documentUpdateBehavior' => DocumentUpdateBehavior::class,
           // 'on EVENT_AFTER_UPDATE'     => ['$this', 'afterUpdateHandler'],
        ]);

The 2nd line in my snippet is commented out, because I am not sure how to write it. I will be glad for guidance!

PS: It might also be important to know that model Document already has some behaviors in its method behaviors()

Is this class your own class or a third party file in your vendor folder?

It’s important to know dependency injection via Di only works if the objects are created via Di. So only via constructor injection or Yii::createObject. It won’t work via new Document().

In case you only want to include this single event in your behaviour you could also just add a public level event

Event::on(
    Document::class, 
    Document::EVENT_AFTER_UPDATE, 
    function() {}
)
1 Like

Thanks for feedback. We have discovered that in our situation Document was not created using Yii::createObject. Probably a problem in our environment.

In short:

We have our own class CActiveRecord which extends ActiveRecord and overrides method instantiate($row). At the end of the method we called return parent::instantiate($row); which caused the problem. Now we are using return Yii::createObject(static::class);

This might help someone.