Observer is a pattern where an object called the subject maintains a list of dependents (observers) and notifies them of any state changes. I implemented this recently to log changes to an Account object, and to notify the account holder if their account had expired – here’s the basics of the code, hopefully it’ll help someone else figure out how the pattern works
<?php
interface Observer
{
public function update(Observable $subject);
}
interface Observable
{
public function attachObserver(Observer $dependent);
public function detachObserver(Observer $dependent);
public function notify();
}
class Account implements Observable
{
public $status;
private $_observers = array();
public function __construct()
{
$this->attachObserver(new Logger());
$this->attachObserver(new Mailer());
}
public function attachObserver(Observer $object)
{
$this->_observers[] = $object;
}
public function detachObserver(Observer $object)
{
foreach ($this->_observers as $index => $observer) {
if ($object == $observer) {
unset($this->_observers[$index]);
}
}
}
public function notify()
{
foreach ($this->_observers as $observer) {
$observer->update($this);
}
}
public function save()
{
$this->notify($this);
$this->notify();
}
}
class Logger implements Observer
{
public function update(Observable $subject)
{
//Update status in log table
echo "Updating status in log table.\n";
}
}
class Mailer implements Observer
{
public function update(Observable $subject)
{
switch (get_class($subject)) {
case "Account":
if ($subject->status == "Expired") {
//send email: "account expired"
echo "Sending account expired email.\n";
}
}
}
}
$account = new Account();
$account->status = "Expired";
$account->save();
The interfaces aren’t strictly necessary, but they help make the whole thing clearer (I hope).
$this->notify($this);