Early previewThis guide is in development. Items tagged verify are still being checked against official docs.
nebx Learn
GitHub
Menu
PHP

PHP

Pragmatic server-side language that powers a large share of the web.

Paradigm
OOP, procedural, functional features
Typing
Dynamic with gradual typing (strict_types)
Memory
Reference counting + cycle collector
Runs
Zend Engine, bytecode + OPcache, optional JIT
Concurrency
Shared-nothing per request; Fibers (8.1)
Behavioral pattern

Observer

Intent

Defines a subscription mechanism that notifies multiple objects about events in the object they observe.

Problem

Customers keep polling the store for a new product, or the store spams everyone.

Solution

The publisher keeps a list of subscribers and notifies them when something happens. Events, signals and pub/sub are all Observer.

Real-world analogy

Think of it like this

A magazine subscription: new issues arrive when they're published, so you don't keep checking the shop.

Structure

association / extends implements / depends on
Publisher - subscribers: Subscriber[]- mainState+ subscribe(s)+ unsubscribe(s)+ notifySubscribers() 12 «interface» Subscriber + update(context) 3 ConcreteSubscribers + update(context) 4 Client 5

Hover or tap a numbered role to highlight it in the diagram.

  1. 1Publisher — Publisher issues events and keeps the subscription list.
  2. 2Publisher — When an event happens, it loops over subscribers and calls update().
  3. 3Subscriber — Subscriber declares the notification interface, usually a single update method.
  4. 4ConcreteSubscribers — Concrete Subscribers react to notifications.
  5. 5Client — Client creates publishers and subscribers and registers subscriptions.

Try it

InteractiveToggle subscribers, then publish an event. Only subscribed objects are notified.
OrderService EmailServiceInventoryAnalytics
Subscribers
// notifications appear here

Code example

observer.php
final class Document implements SplSubject
{
    private SplObjectStorage $observers;
    public string $lastSaved = '';

    public function __construct() { $this->observers = new SplObjectStorage(); }

    public function attach(SplObserver $observer): void { $this->observers[$observer] = null; }
    public function detach(SplObserver $observer): void { unset($this->observers[$observer]); }
    public function notify(): void
    {
        foreach ($this->observers as $observer) {
            $observer->update($this);
        }
    }

    public function save(string $name): void
    {
        $this->lastSaved = $name;
        $this->notify();
    }
}

final class AuditLog implements SplObserver
{
    public function update(SplSubject $subject): void { echo "Saved {$subject->lastSaved}\n"; }
}

Applicability

Use Observer when changes in one object require changes in others, unknown in advance.

Use Observer when some objects should observe others only for a time.

How to implement

  1. Split business logic into a publisher and subscribers
  2. Declare the subscriber interface (often a callback type)
  3. Add subscribe / unsubscribe to the publisher
  4. Notify subscribers when the event happens
  5. Subscribers register with publishers

Pros and cons

Pros

  • Open–Closed: new subscribers without changing the publisher
  • Relationships set up at runtime

Cons

  • Notification order is not guaranteed
  • Forgotten subscriptions can leak memory

Relations with other patterns

Check yourself

Check yourself

When an order is paid, the email, inventory and analytics modules must react, and more may be added later.

Saved in this browser only. Part of Behavioral patterns (0/11), Hands-on: patterns with live demos (0/5).