Gimli includes a flexible event system that allows you to implement the publisher-subscriber pattern in your application. This enables loose coupling between components and makes your code more maintainable and extensible.
The event system is built around these key components:
To trigger an event from anywhere in your application:
// Using the helper function
use function Gimli\Events\publish_event;
publish_event('user.registered', [
'user_id' => 123,
'email' => 'user@example.com'
]);
// Or directly using the Event Manager
use Gimli\Application_Registry;
use Gimli\Events\Event_Manager;
$Event_Manager = Application_Registry::get()->Injector->resolve(Event_Manager::class);
$Event_Manager->publish('user.registered', [
'user_id' => 123,
'email' => 'user@example.com'
]);
There are multiple ways to subscribe to events:
// Using the helper function with a closure
use function Gimli\Events\subscribe_event;
subscribe_event('user.registered', function(string $event, array $data) {
// Handle the event
$user_id = $data['user_id'];
// Do something with the user ID
});
// Using the Event Manager directly with a closure
$Event_Manager = Application_Registry::get()->Injector->resolve(Event_Manager::class);
$Event_Manager->subscribe('user.registered', function(string $event, array $data) {
// Handle the event
}, 10); // Optional priority - higher numbers execute first
For more complex event handling, you can create dedicated event handler classes:
<?php
declare(strict_types=1);
namespace App\Events;
use Gimli\Events\Event_Abstract;
use Gimli\Events\Event;
#[Event('user.registered', description: 'Triggered when a user registers', tags: ['user', 'registration'], priority: 10)]
class User_Registration_Handler extends Event_Abstract {
// Define required parameters
public function getRequiredParameters(): array {
return ['user_id', 'email'];
}
// Define optional parameters
public function getOptionalParameters(): array {
return ['referral_code'];
}
// Custom validation if needed
public function validate(array $args): bool {
return filter_var($args['email'], FILTER_VALIDATE_EMAIL) !== false;
}
// Handle the event
public function execute(string $event_name, array $args = []): void {
$user_id = $args['user_id'];
$email = $args['email'];
// Your event handling logic here
// For example, send a welcome email
}
}
// Register a single event handler class
$Event_Manager = Application_Registry::get()->Injector->resolve(Event_Manager::class);
$Event_Manager->registerClass(User_Registration_Handler::class);
// Register multiple event handler classes
$Event_Manager->register([
User_Registration_Handler::class,
User_Login_Handler::class,
User_Password_Reset_Handler::class
]);
// In Config.php
'events' => [
User_Registration_Handler::class,
User_Login_Handler::class,
User_Password_Reset_Handler::class
]
// Helper function to get event manager
event_manager()->register([
User_Registration_Handler::class,
User_Login_Handler::class,
User_Password_Reset_Handler::class
]);
Event chains allow you to queue multiple events to be executed in sequence:
// Using the helper function
use function Gimli\Events\chain_events;
chain_events()
->add('user.validated', ['user_id' => 123])
->add('user.registered', ['user_id' => 123, 'email' => 'user@example.com'])
->add('notification.send', ['recipient' => 'user@example.com', 'template' => 'welcome'])
->execute();
// Or using the Event Manager directly
$chain = $Event_Manager->chain();
$chain->add('user.validated', ['user_id' => 123])
->add('user.registered', ['user_id' => 123, 'email' => 'user@example.com'])
->add('notification.send', ['recipient' => 'user@example.com', 'template' => 'welcome'])
->execute();
Events can be tagged and given descriptions for better organization and documentation:
#[Event('backup.complete',
description: 'Triggered when a backup process completes',
tags: ['backup', 'system', 'maintenance'],
priority: 5)]
class Backup_Complete_Handler extends Event_Abstract {
// ...
}
You can then retrieve events by tag:
// Get all events with a specific tag
use function Gimli\Events\get_events_by_tag;
$backupEvents = get_events_by_tag('backup');
// Or using the Event Manager
$systemEvents = $Event_Manager->getEventsByTag('system');
// Get events with any of multiple tags
$maintenanceEvents = $Event_Manager->getEventsByTags(['backup', 'maintenance']);
When multiple handlers are subscribed to the same event, you can control their execution order using priorities:
// Higher priority (20) executes before lower priority (10)
$Event_Manager->subscribe('user.registered', $firstHandler, 20);
$Event_Manager->subscribe('user.registered', $secondHandler, 10);
// Or set the priority in the Event attribute
#[Event('user.registered', priority: 20)]
class High_Priority_Handler extends Event_Abstract {
// ...
}
Gimli Framework itself publishes several system events you can hook into:
// Example system events you can subscribe to
$Event_Manager->subscribe('gimli.application.start', function($event, $args) {
// Application has started
$startTime = $args['time'];
});
$Event_Manager->subscribe('gimli.application.end', function($event, $args) {
// Application is finishing
$endTime = $args['time'];
$executionTime = $endTime - $startTime;
});