<p>I don't think that syntax is possible, and in any case it could get a bit confusing. Why not simply use a single anonymous function and then call your individual handlers inside that e.g.</p>
<pre><code>Event::on(
    Entry::class,
    Entry::EVENT_AFTER_SAVE, function(Event $event) {
        $this-&gt;NotifyWhenCookPostedArticle();
        $this-&gt;RunSomethingElse();
        $this-&gt;DoSomethingDifferent();
    }
);

public function NotifyWhenCookPostedArticle() {
    return 'woop';
}
</code></pre>
<p>(Depending on how separate those things are and/or how large and complex you expect the site to be/become, you would typically abstract them further into your Services layer for reusability and encapsulation).</p>

CC BY-SA 4.0
2021-01-25T15:44:48.980Z
Yes you are totally right. Thank you.
Slowwie
CC BY-SA 4.0
2021-01-25T11:31:22.353Z
2021-01-25T11:31:22.353Z
James Smith
<p>I wrote a convient solution - so you can do things like that with invokable Classes:</p>
<p>In AppModule.php:</p>
<pre><code>Event::on(
        Entry::class,
        Entry::EVENT_AFTER_SAVE,
        new OnEntryAfterSave()
    );
</code></pre>
<p>In modules\appmodule\Listeners\OnEntryAfterSave.php</p>
<pre><code>class OnEntryAfterSave
{
    use Invokable, HasActions;

    protected function actions(): array
    {
        return [
            NotifyWhenCookPostedArticle::class,
            RunSomethingElse::class
        ];
    }

}
</code></pre>
<p>For this you have to create this two traits:</p>
<pre><code>trait Invokable
{
    public function __invoke($args)
    {
        foreach (get_class_methods($this) as $method) {
            if (StringHelper::startsWith($method, 'invoke')) {
                $this-&gt;$method($args);
            }
        }
    }
}
</code></pre>
<p>This was just the setup for using as many invoke functions as you want and extend the class more and more. (just for future thinking - to keep it clean and short)</p>
<p>Then the HasActions trait actually listens for actions to call:</p>
<pre><code>trait HasActions
{
    public function invokeActions(ModelEvent $event)
    {
        if (method_exists($this, 'actions')) {
            foreach ($this-&gt;actions() as $action) {
                (new $action)($event);
            }
        }
    }
}
</code></pre>
<p>With this setup you can just create a listener class for each CraftEvent to pass.
This class only holds an array of Action Classes to call.</p>
<p>I like it. It's super clean and reuseable.</p>
<p>You can put it into an Abstract Class to extend from. So you end up with something like this:</p>
<pre><code>class OnEntryAfterSave extends BaseListener
{

    protected function actions(): array
    {
        return [
            NotifyWhenCookPostedArticle::class,
            RunSomethingElse::class
        ];
    }

} 
</code></pre>
<p>Super slick. ;)</p>

CC BY-SA 4.0
2021-01-26T05:58:57.077Z
2021-01-26T06:17:34.850Z
2021-01-26T06:17:34.850Z
Slowwie
<p>Is it possible to register multiple EventHandlers?</p>
<p>I mean something like this:</p>
<pre><code>    Event::on(
        Entry::class,
        Entry::EVENT_AFTER_SAVE,[
           NotifyWhenCookPostedArticle::handle,
           RunSomethingElse::handle,
           DeSomethingDifferent::handle
        ]
</code></pre>
<p>I tried it and got a <code>PHP Warning – yii\base\ErrorException call_user_func() expects parameter 1 to be a valid callback, second array member is not a valid method</code></p>
<p>Is there a notation or helper to get this to work?</p>
<p>Thanks in advance .
Michael</p>

<craft3><events>
Multiple Listeners (Handlers) on Event
# Multiple Listeners (Handlers) on Event

(Asked by: username_0 on 2021-01-25)

Is it possible to register multiple EventHandlers?
I mean something like this:
    Event::on(
        Entry::class,
        Entry::EVENT_AFTER_SAVE,[
           NotifyWhenCookPostedArticle::handle,
           RunSomethingElse::handle,
           DeSomethingDifferent::handle
        ]

I tried it and got a PHP Warning – yii\base\ErrorException call_user_func() expects parameter 1 to be a valid callback, second array member is not a valid method
Is there a notation or helper to get this to work?
Thanks in advance .
Michael

**Tags:** craft3, events


---

## 2 answers

### Answer by username_1 on 2021-01-25. Score: 2 | Accepted answer

I don't think that syntax is possible, and in any case it could get a bit confusing. Why not simply use a single anonymous function and then call your individual handlers inside that e.g.
Event::on(
    Entry::class,
    Entry::EVENT_AFTER_SAVE, function(Event $event) {
        $this->NotifyWhenCookPostedArticle();
        $this->RunSomethingElse();
        $this->DoSomethingDifferent();
    }
);

public function NotifyWhenCookPostedArticle() {
    return 'woop';
}

(Depending on how separate those things are and/or how large and complex you expect the site to be/become, you would typically abstract them further into your Services layer for reusability and encapsulation).

> **Comments:**
> **username_0**: Yes you are totally right. Thank you.  

---

### Answer by username_0 on 2021-01-26. Score: 1

I wrote a convient solution - so you can do things like that with invokable Classes:
In AppModule.php:
Event::on(
        Entry::class,
        Entry::EVENT_AFTER_SAVE,
        new OnEntryAfterSave()
    );

In modules\appmodule\Listeners\OnEntryAfterSave.php
class OnEntryAfterSave
{
    use Invokable, HasActions;

    protected function actions(): array
    {
        return [
            NotifyWhenCookPostedArticle::class,
            RunSomethingElse::class
        ];
    }

}

For this you have to create this two traits:
trait Invokable
{
    public function __invoke($args)
    {
        foreach (get_class_methods($this) as $method) {
            if (StringHelper::startsWith($method, 'invoke')) {
                $this->$method($args);
            }
        }
    }
}

This was just the setup for using as many invoke functions as you want and extend the class more and more. (just for future thinking - to keep it clean and short)
Then the HasActions trait actually listens for actions to call:
trait HasActions
{
    public function invokeActions(ModelEvent $event)
    {
        if (method_exists($this, 'actions')) {
            foreach ($this->actions() as $action) {
                (new $action)($event);
            }
        }
    }
}

With this setup you can just create a listener class for each CraftEvent to pass.
This class only holds an array of Action Classes to call.
I like it. It's super clean and reuseable.
You can put it into an Abstract Class to extend from. So you end up with something like this:
class OnEntryAfterSave extends BaseListener
{

    protected function actions(): array
    {
        return [
            NotifyWhenCookPostedArticle::class,
            RunSomethingElse::class
        ];
    }

} 

Super slick. ;)


---

