The Standard PHP Library includes what some resources call a reference implementation of the Observer pattern, by way of the SplSubject
and SplObserver
classes. For the life of me, I can't figure out how these are very useful with no way to pass actual events or any other information along with the notifications:
class MySubject implements SplSubject {
protected $_observers = [];
public function attach(SplObserver $observer) {
$id = spl_object_hash($observer);
$this->_observers[$id] = $observer;
}
public function detach(SplObserver $observer) {
$id = spl_object_hash($observer);
if (isset($this->_observers[$id])) {
unset($this->_observers[$id]);
}
}
public function notify() {
foreach ($this->_observers as $observer) {
$observer->update($this);
}
}
}
class MyObserver implements SplObserver {
public function update(SplSubject $subject) {
// something happened with $subject, but what
// was it???
}
}
$subject = new MySubject();
$observer = new MyObserver();
$subject->attach($observer);
$subject->notify();
It seems like these interfaces are pretty much useless for any real world problem. Can someone enlighten me?
Edit:
Here's my biggest problem with the interface (although there are others):
public function update(SplSubject $subject, Event $event) { /* ... */ }
...nets the following fatal error:
PHP Fatal error: Declaration of MyObserver::update() must be compatible with SplObserver::update(SplSubject $SplSubject)
Edit #2:
Making the additional parameters optional by giving them defaults prevents the fatal error and provides a way to pass context, making implementations worthwhile. I wasn't previously aware of this, so this pretty much answers my question. The solution is to pass your own event/message data, and check for its existance inside SplObserver::update()
.
You can implement the update method with an optional parameter and still satisfy the SplSubject interface.
class MyObserver implements SplObserver {
public function update(SplSubject $subject, $eventData = null) {
if (is_null($eventData))
// carefull
}
}