Event Bus and Observer Pattern in PHP: Implementation and Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Event Bus and Observer Pattern in PHP



In modern PHP web application development, there is often a need to flexibly respond to various events: sending an email after registration, logging user actions, updating the cache when data changes. The Observer pattern and its extension — Event Bus — are ideal for these purposes.



Observer Pattern: Basics



The Observer pattern is a behavioral design pattern that creates a subscription mechanism allowing one object to watch and react to events occurring in other objects. Main components:



  • Subject — the object that generates events
  • Observer — the object that reacts to events
  • Event — information about the action that occurred


Event Bus: Evolution of Observer



Event Bus is a centralized bus that manages all events in an application. Unlike the classic Observer, where subscription is tightly coupled to the subject, Event Bus provides:



  • Loose coupling between senders and receivers
  • Ability to add/remove handlers at runtime
  • Global access to the bus from any part of the application
  • Simplified testing and debugging


Example Implementation of Event Bus in PHP



Let's create a simple yet functional implementation of Event Bus, compatible with PSR-14 (Event Dispatcher).



<?php// Event interfaceinterface EventInterface{    public function getName(): string;}

// Base eventclass UserRegisteredEvent implements EventInterface{ public function __construct( private string $email, private string $username ) {}

public function getName(): string { return 'user.registered'; }

public function getEmail(): string { return $this->email; }

public function getUsername(): string { return $this->username; }}

// Handler interfaceinterface EventHandlerInterface{ public function handle(EventInterface $event): void;}

// Event Busclass EventBus{ private array $listeners = [];

public function addListener(string $eventName, EventHandlerInterface $handler): void { $this->listeners[$eventName][] = $handler; }

public function removeListener(string $eventName, EventHandlerInterface $handler): void { if (!isset($this->listeners[$eventName])) { return; }

$this->listeners[$eventName] = array_filter( $this->listeners[$eventName], fn($h) => $h !== $handler ); }

public function dispatch(EventInterface $event): void { $eventName = $event->getName();

if (!isset($this->listeners[$eventName])) { return; }

foreach ($this->listeners[$eventName] as $handler) { $handler->handle($event); } }}?>


Practical Usage



Now let's create handlers and demonstrate the bus in action:



<?php// Email sending handlerclass SendWelcomeEmailHandler implements EventHandlerInterface{    public function handle(EventInterface $event): void    {        if (!$event instanceof UserRegisteredEvent) {            return;        }

echo "Sending welcome email to {$event->getEmail()}"; // mail($event->getEmail(), 'Welcome!', '...'); }}

// Logging handlerclass LogUserRegistrationHandler implements EventHandlerInterface{ public function handle(EventInterface $event): void { if (!$event instanceof UserRegisteredEvent) { return; }

Recommendations