Content · Web Development · PHP

Applying the Observer Pattern with PHP Events

An observer receives events from a publisher without coupling the publisher to every downstream action.

1 views Published Oct 17, 2026 Updated Oct 17, 2026 Admin

An observer receives events from a publisher without coupling the publisher to every downstream action.

What It Does and When to Use It


Implement a simple dispatcher with separately registered listeners. Direct PHP code exposes the underlying operation clearly; a framework can supply lifecycle hooks, dependency wiring and retries.

Requirements, Inputs and Expected Behavior


Confirm the runtime, extension, environment variables, and permissions before running the examples in production. Keep listeners predictable, isolate failures and avoid recursive event chains.

Example 1: Basic Operation


Implement a simple dispatcher with separately registered listeners.

<?php
final class Dispatcher {
     private array $listeners = [];
     public function on(string $name, callable $listener): void { $this->listeners[$name][] = $listener; }
     public function dispatch(string $name, object $event): void {
         foreach ($this->listeners[$name] ?? [] as $listener) $listener($event);
     }
 }
 $events = new Dispatcher();
 $events->on('invoice.created', static function (object $e): void { echo $e->id; });
 $events->dispatch('invoice.created', (object)['id' => 23]);

Example 2: Behavior and Validation


Separate several reactions from the action that published an event.

<?php
$handlers = [static fn (int $id) => "audit:$id", static fn (int $id) => "email:$id"];
 $results = array_map(static fn (callable $f) => $f(42), $handlers);
 print_r($results);

Practical Example: Application Use


Pass structured event data and keep validation explicit.

<?php
$listeners = [];
 $listeners['order.paid'][] = static function (array $event): void {
     if (($event['amount'] ?? 0) <= 0) throw new InvalidArgumentException('Positive amount required');
     echo 'Recorded payment ', $event['id'];
 };
 foreach ($listeners['order.paid'] as $listen) $listen(['id' => 'p-13', 'amount' => 85]);

Important Behavior and Edge Cases


The second example highlights: Separate several reactions from the action that published an event. The practical example adds: Pass structured event data and keep validation explicit.

Comparison with Related Approaches


ApproachWhat changes
Direct operation versus framework-managed integrationDirect PHP code exposes the underlying operation clearly; a framework can supply lifecycle hooks, dependency wiring and retries.
Choosing safelyChoose based on deployment requirements and verify actual behavior rather than assuming defaults.

Common Beginner Mistakes


MistakeCorrect approach
Assuming successful execution proves the result is usableCheck the return value, required extension, and observable output of the specific operation.
Ignoring runtime and environment differencesVerify PHP version, SAPI, operating system, service access, and permissions before deployment.
Skipping operational constraintsKeep listeners predictable, isolate failures and avoid recursive event chains.

Key Takeaways


  • An observer receives events from a publisher without coupling the publisher to every downstream action.
  • Pass structured event data and keep validation explicit.
  • Choose based on deployment requirements and verify actual behavior rather than assuming defaults.
Share this resourceSend this page to someone who may find it useful.