maxkaemmerer/events
, (*1)
Description:
This library offers interfaces and implementations for a simple event, event-subscriber, event-courier structure., (*2)
This is of course not an original idea, but my preferred and fairly simple implementation., (*3)
The code is fully tested, I however do not take responsibility for use in production., (*4)
Use at your own risk., (*5)
Installation:
composer require maxkaemmerer/events
, (*6)
Usage:
Generally you don't want to subscribe each EventSubscriber
by hand. You might want to use dependency injection via a container or service-manager., (*7)
(An example for the Symfony Framework would be using a CompilerPass
), (*8)
You would also want to inject the EventCourier
itself via dependency injection wherever you need it., (*9)
Feel free to create your own implementations of EventCourier
, Subscription
and Payload
if you require something more advanced., (*10)
Subscribe an EventSubscriber:
Subscribe an EventSubscriber
to the EventCourier
. The EventSubscriber
's subscription()
method returns a Subscription
, which contains the name of the Event
that the EventSubscriber
subscribes to and the priority at which it wants to be notified., (*11)
(The higher the priority, the earlier the EventSubscriber
get notified of the Event
, assuming there are other EventSubscriber
s with lower priority.), (*12)
Best practice would be using the fully qualified class name of the event. MyEvent::class
, (*13)
The EventSubscriber::on($event)
method is where your actual domain logic happens., (*14)
Feel free to inject services, a container, or whatever else you need, into your EventSubscriber
s., (*15)
$courier = new SimpleEventCourier();
$courier->subscribe(new class implements EventSubscriber
{
/**
* @param Event $event
*/
public function on(Event $event): void
{
echo 'Notify Shipping!' . PHP_EOL;
}
/**
* @return EventSubscription
*/
public function subscription(): EventSubscription
{
return Subscription::fromEventNameAndPriority('PaymentReceived', 50);
}
});
Dispatch an Event:
Dispatching an Event
causes the EventCourier
to notify all EventSubscriber
s, who's Subscription::event()
method matches the Event
's name, specified by Event:name()
, and calls their EventSubscriber::on($event)
method in order of priority., (*16)
IMPORTANT: EventSubscriber
's and the EventCourier
never return anything., (*17)
...
// The EventSubscriber was subscribed
echo 'Payment received.' . PHP_EOL;
$courier->dispatch(new class implements Event
{
public function payload(): EventPayload
{
// the payload should of course be built or set in the constructor
return Payload::fromArray(['price' => '99.99€', 'method' => 'creditCard', 'timestamp' => '12345678']);
}
public function name(): string
{
// best practice would be using the fully qualified class name MyEvent::class
return 'PaymentReceived';
}
});
Result:, (*18)
Payment received.
Notify Shipping!
Full Example:
<?php
require_once __DIR__ . '/vendor/autoload.php';
use MaxKaemmerer\Events\Event;
use MaxKaemmerer\Events\EventPayload;
use MaxKaemmerer\Events\EventSubscriber;
use MaxKaemmerer\Events\EventSubscription;
use MaxKaemmerer\Events\Implementations\Payload;
use MaxKaemmerer\Events\Implementations\SimpleEventCourier;
use MaxKaemmerer\Events\Implementations\Subscription;
$courier = new SimpleEventCourier();
$courier->subscribe(new class implements EventSubscriber
{
/**
* @param Event $event
*/
public function on(Event $event): void
{
echo 'Notify Shipping!' . PHP_EOL;
}
/**
* @return EventSubscription
*/
public function subscription(): EventSubscription
{
return Subscription::fromEventNameAndPriority('PaymentReceived', 50);
}
});
$courier->subscribe(new class implements EventSubscriber
{
/**
* @param Event $event
*/
public function on(Event $event): void
{
echo 'Send Receipt! Payed: ' . $event->payload()->get('price') . PHP_EOL;
}
/**
* @return EventSubscription
*/
public function subscription(): EventSubscription
{
return Subscription::fromEventNameAndPriority('PaymentReceived', 60);
}
});
echo 'Payment received.' . PHP_EOL;
$courier->dispatch(new class implements Event
{
public function payload(): EventPayload
{
// the payload should of course be built or set in the constructor
return Payload::fromArray(['price' => '99.99€', 'method' => 'creditCard', 'timestamp' => '12345678']);
}
public function name(): string
{
// best practice would be using the fully qualified class name MyEvent::class
return 'PaymentReceived';
}
});
Result:, (*19)
Payment received.
Send Receipt! Payed: 99.99€
Notify Shipping!
Send Receipt! Payed: 99.99€
gets echoed first since the corresponding EventSubscriber
's Subscription::priority()
is higher., (*20)