Events & hooks & friends

I’d like to add “actions to happen when conditions are met” into a slim app. After spending 2 hours googling keywords such as events, hooks, triggers, observers, ddd, etc. I eventually got lost in the terminology. I’m not a fluent developer so I’m hoping for advice directing me in the right direction.

I got a MVC structured Slim 4 base. On the model side, the functions do only validation and data handling (via PHP-MySQLi-Database-Class which I prefer over full blown ORMs). My goal is to

  • trace users’ activity (i.e. database inserts and updates, file uploads and deletes)
  • log authentication attempts
  • eventually send realtime notifications in a far far feature (i.e. via ratchet or similar)

My trivial approach would be to write a global “event emitter” function which I’d type in manually into all class methods that handle data. This “event emitter” would store events and maybe some payload data in, say, redis or similar. On each app run, there’d be an “event listener” which would run some closures/methods as configured.

Now this surely has been done many times before. I assume, that there’s a simple way / usual, how I could run a callback before a function/method returns (without manually typing out the event emitter function everywhere) such as with https://pecl.php.net/package/uopz. But since I didn’t see this used in such a way, I assume it has some drawback coming along (i.e. a performance hit, not being as flexible as I imagine it to be, etc.) so I started looking all over to finally get overwhelmed with too much information :slight_smile:

Any tips, recommendations? Are there existing packages/middleware & some example code with Slim?
Thanks lots!

To me it sounds like you want logging, perhaps Monolog or a wrapper around your DB-class autowired into the appropriate classes. If you want to add a notification system you can also write to a Redis instance and have your clients subscribe to it over websocket.

@killua Have you tried the Symfony EventDispatcher?

This is a blast from the past, I didn’t notice the answers here :man_facepalming: @odan , yep, that’s exactly what I meant :slight_smile: I tried the symfony component but being lazy to read all the docs, it felt like an overkill with no straightforward example for my usecase. I ended up with using https://sabre.io/event/emitter/ and all seems to work great!

Here you can find fully functional slim4-psr14 starter. Take a look:

slim4-psr14-starter

I seem to have an edge case when events don’t get emitted … @tj_gumis , thanks lots, I tried to refer to your code but I’m not that fluent in php to see what i’m doing wrong. Basically, my events don’t work in classes. My app

  1. sets up a container & adds events and, i.e. my auth class to it … something like

    $container->set(‘events’, function () {
    return new Emitter();
    });

    $container->set(‘auth’, function (Container $c) {
    return new Auth($c->get(‘events’));
    });

  2. adds the event listeners, i.e.

    $ev = $container->get(‘event s’);
    $ev->on(‘core.auth.user.create’, function($entityId) {
    $fp = fopen("/var/www/html/private/test".$entityId.".txt",“wb”);
    fwrite($fp,‘user ". $entityId. " created.’);
    fclose($fp);
    });

  3. adds middleware

  4. adds routes.

When I try to $this->c->events->emit('core.auth.user.create', [$id]); in the Auth class, things stop working. Doing the same in a controller or middleware works.

I’m thought there’s a problem in when what gets initialized in the container, but I could neither confirm this, nor figure out a way around this. Any ideas what my antipattern might be?

I’ve been recently in love with events based approach so if you find some time I will guide you step by step with pleasure. We just need to fix some hangouts appointment. Just let me know.