Links

Dispatching Events

Events PHP
Previous pages provide the background on how to handle event messages in your application. The dispatching process is the starting point for event message. You will mostly send events after successfully handling Command Message, examples will base on that assumption.
You can inject EventBus and send events wherever necessary. Ecotone tries not to impose any specific solutions.

Event Bus

Event Bus is special type of Messaging Gateway.
namespace Ecotone\Modelling;
interface EventBus
{
// 1
public function publish(object $event, array $metadata = []) : void;
// 2
public function publishWithRouting(string $routingKey, mixed $event = [], string $eventMediaType = MediaType::APPLICATION_X_PHP, array $metadata = []) : void;
}

Publishing

Event is routed to the Handler by class type.
Command Handler
class CloseTicketCommandHandler
{
#[CommandHandler]
public function closeTicket(CloseTicketCommand $command, EventBus $eventBus) : void
{
$eventBus->publish(new TicketWasClosed($command->getTicketId()));
}
}
Event Handler
class NotificationService
{
#[EventHandler]
public function closeTicket(TicketWasClosed $event) : void
{
// notify about closing the ticket
}
}

Publishing with routing

Is used with Command Handlers,routed by name and converted using Converter if needed. Sending events by name instead of class type, may be found useful in integration with external application, when events are in different Media Type than PHP class.
Command Handler
class CloseTicketCommandHandler
{
#[CommandHandler]
public function closeTicket(CloseTicketCommand $command, EventBus $eventBus) : void
{
$eventBus->publishWithRouting(
"ticket.wasClosed",
'{"ticketId": 123}',
"application/json"
);
}
}
Event Handler
class NotificationService
{
#[EventHandler("ticket.wasClosed")]
public function closeTicket(TicketWasClosed $event) : void
{
// notify about closing the ticket
}
}
JSON will be automatically converted to specific class type hinted in method declaration of Event Handler. You could also use in here simple array if you have JSON to array Converter or a string, if you like to receive JSON string.

Publishing from Aggregate

Ecotone does provide possibility to automatically gather events from Aggregate and publish them using EventBus.

State-Stored Aggregate

To tell Ecotone, which method it should use for retrieving Event objects when using State-Stored Aggregate mark method containing events with annotation @AggregateEvents. After handling Command or Event on Aggregate events will be published.
#[AggregateEvents]
public function getRecordedEvents() : array
Events will be automatically retrieved and published after handling Commands in your Aggregate.

Use quick way to publish events

You don't need to create your own method within aggregate, you may reuse predefined trait for that WithAggregateEvents.
#[Aggregate]
final class Order
{
use WithAggregateEvents;
public function __construct(
#[AggregateIdentifier] public readonly string $orderId
) {
$this->recordThat(new OrderWasPlaced($orderId));
}
#[CommandHandler]
public static function create(PlaceOrder $command)
{
return new self($command->orderId);
}
(...)

Event Sourcing Aggregate

When using Event Sourcing Aggregate you do not need to do anything extra. Each method should return events after handling, those events will automatically published using Event Bus.
#[CommandHandler]
public function deposit(DepositMoney $command): array
{
return [new MoneyWasDeposited($command->walletId, $command->amount)];
}
Events published from aggregate, are publish by class name and routing, if event is named. #[NamedEvent("order_was_placed")] class OrderWasPlaced