Event Bus and Observer Pattern in PHP: From Theory to Practice
In modern PHP development, there is an increasing need to create loosely coupled, flexible, and extensible systems. Two key tools for achieving this goal are the Observer pattern and its more advanced abstraction — the Event Bus. In this article, we will break down how to implement both approaches in PHP and show when to choose which tool.
What is the Observer Pattern?
The Observer pattern is a behavioral design pattern that defines a one-to-many dependency between objects. When one object (the subject) changes its state, all dependent objects (observers) are automatically notified.
A simple implementation of Observer in PHP:
<?phpinterface Observer { public function update(string $event, $data): void;}
interface Observable { public function attach(Observer $observer): void; public function detach(Observer $observer): void; public function notify(string $event, $data = null): void;}
class UserManager implements Observable { private array $observers = [];
public function attach(Observer $observer): void { $this->observers[] = $observer; }
public function detach(Observer $observer): void { $this->observers = array_filter( $this->observers, fn($obs) => $obs !== $observer ); }
public function notify(string $event, $data = null): void { foreach ($this->observers as $observer) { $observer->update($event, $data); } }
public function registerUser(string $name): void { // Registration logic echo "User $name registered."; $this->notify('user.registered', ['name' => $name]); }}
class EmailNotifier implements Observer { public function update(string $event, $data): void { if ($event === 'user.registered') { echo "Sending welcome email for {$data['name']}."; } }}
class Logger implements Observer { public function update(string $event, $data): void { echo "Logging event: $event"; }}
// Usage$userManager = new UserManager();$userManager->attach(new EmailNotifier());$userManager->attach(new Logger());
$userManager->registerUser('Ivan');?>Drawbacks of the Classic Observer
- Tight coupling — observers must know about the subject.
- Lack of flexibility — managing many heterogeneous events is difficult.
- Testing issues — each subject contains a list of observers.
Event Bus — Evolution of the Observer Pattern
Event Bus is a centralized mediator between event publishers and their subscribers. Instead of each subject object managing a list of observers, all subscriptions and notifications pass through a single bus.
Implementing an Event Bus in PHP
<?phpclass EventBus { private array $listeners = [];
public function subscribe(string $event, callable $handler): void { $this->listeners[$event][] = $handler; }
public function unsubscribe(string $event, callable $handler): void { if (!isset($this->listeners[$event])) { return; } $this->listeners[$event] = array_filter( $this->listeners[$event], fn($h) => $h !== $handler ); }
public function dispatch(string $event, $payload = null): void { if (!isset($this->listeners[$event])) { return; } foreach ($this->listeners[$event] as $handler) { call_user_func