www.hubleto.eu Reddit User Guide Stack Overflow LinkedIn Community Report an issue

Registering event listeners using $eventManager->addEventListener()

A listener class does nothing until it is registered for an event. Register listeners in your app's Loader::init().

Syntax

$this->eventManager()->addEventListener(string $event, EventListenerInterface $listener);
Argument Description
$event Name of the event, e.g. 'onModelAfterUpdate'. The listener must have a method with this name.
$listener An instance of the listener. Create it with $this->getService(...).

Arguments of addEventListener().

Examples

apps/AuditLogs/Loader.php
public function init(): void
{
  parent::init();

  $this->router()->get([
    '/^audit-logs(\/(?<recordId>\d+))?\/?$/' => Controllers\AuditLogs::class,
  ]);

  $this->eventManager()->addEventListener(
    'onModelAfterCreate',
    $this->getService(EventListeners\LogCreatedRecord::class)
  );

  $this->eventManager()->addEventListener(
    'onModelAfterUpdate',
    $this->getService(EventListeners\LogUpdatedRecord::class)
  );

  $this->eventManager()->addEventListener(
    'onModelAfterDelete',
    $this->getService(EventListeners\LogDeletedRecord::class)
  );
}
apps/Workflow/Loader.php: two listeners for one event
$this->eventManager()->addEventListener(
  'onModelAfterUpdate',
  $this->getService(EventListeners\SaveWorkflowHistory::class)
);

$this->eventManager()->addEventListener(
  'onModelAfterUpdate',
  $this->getService(EventListeners\WorkflowAutomat::class)
);
apps/Notifications/Loader.php: a model event and a custom event
$this->eventManager()->addEventListener(
  'onModelAfterUpdate',
  $this->getService(EventListeners\NotifyUpdatedRecord::class)
);

$this->eventManager()->addEventListener(
  'onSendEmailNotification',
  $this->getService(EventListeners\EmailNotifications::class)
);
apps/Usage/Loader.php: a controller event
$this->eventManager()->addEventListener(
  'onControllerBeforeInit',
  $this->getService(EventListeners\LogUsage::class)
);

How the event manager calls listeners

Hubleto\Framework\Services\EventManager
public function addEventListener(string $event, EventListenerInterface $listener): void
{
  if (!isset($this->listeners[$event])) $this->listeners[$event] = [];
  $this->listeners[$event][] = $listener;
}

public function getEventListeners(): array
{
  return $this->listeners;
}

public function fire(string $event, array $args): void
{
  if (isset($this->listeners[$event]) && is_array($this->listeners[$event])) {
    foreach ($this->listeners[$event] as $listener) {
      call_user_func_array([$listener, $event], $args);
    }
  }
}

Consequences:

Register the same listener for more events

$syncListener = $this->getService(EventListeners\SyncToExternalCrm::class);

$this->eventManager()->addEventListener('onModelAfterCreate', $syncListener);
$this->eventManager()->addEventListener('onModelAfterDelete', $syncListener);

Register conditionally

Registration is code, so it can depend on configuration:

$syncEnabled = $this->configAsBool('syncEnabled');

if ($syncEnabled) {
  $this->eventManager()->addEventListener(
    'onModelAfterUpdate',
    $this->getService(EventListeners\SyncToExternalCrm::class)
  );
}

Where to register

Debugging

List all registered listeners, e.g. in a temporary controller or a test:

foreach ($this->eventManager()->getEventListeners() as $event => $listeners) {
  foreach ($listeners as $listener) {
    $this->logger()->info($event . ' -> ' . get_class($listener));
  }
}

Complete example

1. src/apps/MyFirstApp/EventListeners/LogBookChanges.php
<?php declare(strict_types=1);

namespace Hubleto\App\Custom\MyFirstApp\EventListeners;

use Hubleto\App\Custom\MyFirstApp\Models\Book;
use Hubleto\Framework\Interfaces\ModelInterface;

class LogBookChanges extends \Hubleto\Framework\EventListener implements \Hubleto\Framework\Interfaces\EventListenerInterface
{
  public function onModelAfterUpdate(ModelInterface $model, array $originalRecord, array $savedRecord): void
  {
    if (!($model instanceof Book)) return;

    $changedColumns = array_keys($model->diffRecords($originalRecord, $savedRecord));
    $this->logger()->info('Book #' . $savedRecord['id'] . ' changed: ' . join(', ', $changedColumns));
  }
}
2. src/apps/MyFirstApp/Loader.php
public function init(): void
{
  parent::init();

  // ... routes

  $this->eventManager()->addEventListener(
    'onModelAfterUpdate',
    $this->getService(EventListeners\LogBookChanges::class)
  );
}