# Registering event listener with dependencies

**URL:** <https://discourse.cakephp.org/t/registering-event-listener-with-dependencies/12848>\
**Category:** Uncategorized\
**Created:** [May 11, 2026, 1:10pm UTC](https://discourse.cakephp.org/t/registering-event-listener-with-dependencies/12848 "2026-05-11T13:10:49Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Schroeder](https://avatars.discourse-cdn.com/v4/letter/s/ec9cab/32.png) [@Schroeder](https://discourse.cakephp.org/u/Schroeder)\
**Post date:** [May 11, 2026, 1:10pm UTC](https://discourse.cakephp.org/t/registering-event-listener-with-dependencies/12848/1 "2026-05-11T13:10:49Z")

</div>

Hello,

This is in fact about 2 seperate questions.

I’m trying to implement some custom listener which is supposed to delete orphaned entites from a specific table.

1. I am using the DI container to wire everything together, so how would I go about it here?

The doc states to register your listener in either the application or plugin class and then proceeds to provide an example. But in the example, the listener class apparently has no dependencies:

```auto
    public function events(EventManagerInterface $eventManager): EventManagerInterface
    {
        $statistics = new UserStatistic();
        $eventManager->on($statistics);

        return $eventManager;
    }

```

1. My inital attempt was to use the table class as a listener, since it already implements `EventListenerInterface` and the logic is strongly related to the table class, but to no avail. The registered callback is never triggered:

_In controller_

```auto
EventManager::instance()->dispatch(new Event('InvoiceDrafts.created', $this));

```

_In table class_

```auto
    public function implementedEvents(): array
    {
        return array_merge(parent::implementedEvents(), [
            'InvoiceDrafts.created' => 'cleanUp',
        ]);
    }

    [...]

    public function cleanUp(EventInterface $event): int
    {
        return $this->deleteAll([
            'buyer_id IS' => null,
            'biller_id IS' => null,
        ]);
    }

```

Why is this not working? I did not plan to create a behaviour here because apparently behaviours `provide a convenient way to package up behavior that is common across many models. `.

Thanks

---

<div class="post-metadata">

**Author:** ![KevinPfeifer](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/kevinpfeifer/32/3365_2.png) [@KevinPfeifer](https://discourse.cakephp.org/u/KevinPfeifer)\
**Post date:** [May 12, 2026, 7:47pm UTC](https://discourse.cakephp.org/t/registering-event-listener-with-dependencies/12848/2 "2026-05-12T19:47:19Z")

</div>

Hi @Schroeder,

combining Event Listeners and the DI container is something, that is on our list. But for now you will have to manage the event objects and their constructor dependencies yourself till this is implemented more nicely into CakePHP (maybe in v6)

* * *

But about Event Listeners in general there are a few things you may seem to misunderstand:

## Event Listener scope

CakePHP allows you to add listeners globally or just to specific areas of the framework (like tables, controllers, views etc.)

You are trying to add a event listener to the table class but then dispatch the Event globally via the global event manager. This cannot work, as the dispatched event doesn’t know which table object it needs to “give” the event to.

The global event manager just knows of its own - global - event Listeners which are usually added in `config/bootstrap.php` or `Application::bootstrap` or the new `Application::events` hook. Those are all places where you can add **global event listeneres**

To make your example worke you need to dispatch the event on the table instance, not on the global event manager via doing something like this

```auto
$this->InvoiceDrafts->dispatchEvent('InvoiceDrafts.created', [], $this);

```

Then your cleanup method will be called.

* * *

## Event Listener registration

Another important parts about event listeners is the fact, that they - obviously - they need to registerd before the event is being dispatched.

In your example this wasn’t really a problem, as you “registered” your event listener inside the table class and therefore whenever the table object is being created.

In the case of a controller method the table instance is being created the moment you try to access the property `$this->InvoiceDrafts`so with the adjusted code from above it will be registered before the event is actually being dispatched.

* * *

I hope this helped you understand why your code didn’t work and how you can get it working again 😉

---

<div class="post-metadata">

**Author:** ![KevinPfeifer](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/kevinpfeifer/32/3365_2.png) [@KevinPfeifer](https://discourse.cakephp.org/u/KevinPfeifer)\
**Post date:** [May 12, 2026, 7:48pm UTC](https://discourse.cakephp.org/t/registering-event-listener-with-dependencies/12848/3 "2026-05-12T19:48:45Z")

</div>

Also FYI: There is a proposed Attribute based system you can see in [RFC - 6.0 - Attribute-Based Event Listeners · Issue #19297 · cakephp/cakephp · GitHub](https://github.com/cakephp/cakephp/issues/19297) which may get implemented in CakePHP 6

---

<div class="post-metadata">

**Author:** ![Schroeder](https://avatars.discourse-cdn.com/v4/letter/s/ec9cab/32.png) [@Schroeder](https://discourse.cakephp.org/u/Schroeder)\
**Post date:** [May 13, 2026, 9:18am UTC](https://discourse.cakephp.org/t/registering-event-listener-with-dependencies/12848/4 "2026-05-13T09:18:45Z")

</div>

Thanks for the explanation. What is the CakePHP way or convention - if there is one - in the described use case?

1. attaching the cleanup logic to the table class or
2. registering a global event listener via `application.php` and dispatching the event on the global `EventManager`

Also, what if several tables listen to the `InvoiceDrafts.created` event? Would I then have to dispatch the event on all of these table classes in my controller, like

```auto
$this->someTable->dispatch()
$this->otherTable->dispatch()

```

---

<div class="post-metadata">

**Author:** ![KevinPfeifer](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/kevinpfeifer/32/3365_2.png) [@KevinPfeifer](https://discourse.cakephp.org/u/KevinPfeifer)\
**Post date:** [May 13, 2026, 10:10am UTC](https://discourse.cakephp.org/t/registering-event-listener-with-dependencies/12848/5 "2026-05-13T10:10:32Z")

</div>

As always there are multiple ways to do this 😃

I personally extract pretty much all my shared logic into service classes and then inject them wherever I need them. You can watch this video here where I explain the whole namespace concept in PHP [https://www.youtube.com/watch?v=z3E\_UdH1XeE](https://www.youtube.com/watch?v=z3E_UdH1XeE)

This of course puts the burdon on you to know how you architect your software, so you’d need to have a clear image on how you want your “flow” to work in your usecase.

* * *

Coming back to your problem: As far as I can tell you want to have some sort of global trigger/event which calls the `cleanup` method on any table class which is associated to that trigger/event.

You could technically achieve that via doing 1 additional thing (which I would NOT recommend)

```auto
EventManager::instance()->on(
    TableRegistry::getTableLocator()->get('InvoiceDrafts')
);

```

This adds the table instance the to global event listener and therefore your initial call will also work.

But I would NOT recommend instantiating table objects if you don’t need them.

If you always need to cleanup a table instance which is already present in your controller you can always just call the table method directly via `$this->InvoiceDrafts→cleanup();`

But if you NEED to listen on the same event on multiple table instances and do logic on that I’d rather extract that into some sort of `CleanupService` class and do the logic in there.

You can use the LocatorAwareTrait to fetch/create table objects inside any class you desire.

---

<div class="post-metadata">

**Author:** ![Schroeder](https://avatars.discourse-cdn.com/v4/letter/s/ec9cab/32.png) [@Schroeder](https://discourse.cakephp.org/u/Schroeder)\
**Post date:** [May 13, 2026, 10:46am UTC](https://discourse.cakephp.org/t/registering-event-listener-with-dependencies/12848/6 "2026-05-13T10:46:38Z")

</div>

Alright. What I get from your response it that “mis-using” table classes as event listeners for custom events (not ORM-events like `beforeMarshal`) is not really the CakePHP way, even if the logic is closely related to the table class itself. Thanks.

---

<div class="post-metadata">

**Author:** ![KevinPfeifer](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/kevinpfeifer/32/3365_2.png) [@KevinPfeifer](https://discourse.cakephp.org/u/KevinPfeifer)\
**Post date:** [May 13, 2026, 11:20am UTC](https://discourse.cakephp.org/t/registering-event-listener-with-dependencies/12848/7 "2026-05-13T11:20:55Z")

</div>

Thats at least how I see it. Maybe @dereuromark or @ADmad have something else to say about that.

---

<div class="post-metadata">

**Author:** ![KevinPfeifer](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/kevinpfeifer/32/3365_2.png) [@KevinPfeifer](https://discourse.cakephp.org/u/KevinPfeifer)\
**Post date:** [May 13, 2026, 1:27pm UTC](https://discourse.cakephp.org/t/registering-event-listener-with-dependencies/12848/8 "2026-05-13T13:27:25Z")

</div>

I just created this PR which as a proof of concept on how DI integration for Event Listeners could look like.

> <https://github.com/cakephp/cakephp/pull/19437>
>
> Refs: https://github.com/cakephp/cakephp/issues/19297 & https://github.com/cakep…hp/cakephp/issues/19421
> 
> We are slowly but surely getting to a really good state to register event listeners :D 
> 
> This PR adds the ability to define a list of Event-Listener FQCN's which get automatically registered in the global event manager + get those objects get fetched from the DI container, so constructor injection inside those listeners works as expected.
> 
> This is working for both the base application as well as plugin specific event listeners.
> 
> \## Up for discussion
> 
> Currently for the base application I used the \`App.EventListeners\` configure value to make it easily adjustable which FQCN's should be registered like this.
> 
> This is of course not possible in plugins, so for those the current way would be to overwrite the \`$eventListeners\` property. But I guess a proper method to set/update that property would be better. But not sure what the APi for that would be so that users and plugin devs have an easy time setting and adjusting those values.
