Observer
composer require php-standard-library/observer
The Observer component provides two interfaces for the classic Observer design pattern. A subject maintains a list of observers and notifies them when something changes. PSL's interfaces are generic, so observers receive the concrete subject type rather than a vague base class.
Design
SubjectInterface-- The object being watched. It cansubscribe(),unsubscribe(), andnotify()observers.ObserverInterface<T>-- The watcher. Itsupdate()method receives the subject that triggered the notification, fully typed asT.
Usage
The following example demonstrates a complete Subject/Observer implementation, including wiring them together:
use Psl\IO;
use Psl\Observer;
use Psl\Vec;
final class Inventory implements Observer\SubjectInterface
{
/** @var list<Observer\ObserverInterface<Inventory>> */
private array $observers = [];
private int $stock = 0;
public function subscribe(Observer\ObserverInterface $observer): void
{
$this->observers[] = $observer;
}
public function unsubscribe(Observer\ObserverInterface $observer): void
{
$this->observers = Vec\filter($this->observers, static fn($o) => $o !== $observer);
}
public function notify(): void
{
foreach ($this->observers as $observer) {
$observer->update($this);
}
}
public function restock(int $quantity): void
{
$this->stock += $quantity;
$this->notify();
}
public function getStock(): int
{
return $this->stock;
}
}
/** @implements Observer\ObserverInterface<Inventory> */
final class StockAlert implements Observer\ObserverInterface
{
/** @param Inventory $subject */
public function update(Observer\SubjectInterface $subject): void
{
if ($subject->getStock() > 100) {
IO\write_line('Alert: stock is now %d (above threshold)', $subject->getStock());
}
}
}
// Wiring it together
$inventory = new Inventory();
$alert = new StockAlert();
$inventory->subscribe($alert);
$inventory->restock(150); // StockAlert::update() is called
$inventory->unsubscribe($alert);
$inventory->restock(50); // No alert -- observer was removed
IO\write_line('Final stock: %d', $inventory->getStock());
See src/Psl/Observer/ for the full API.