Observable.php
<?php
trait Observable
{
protected $observers = [];
/**
* Adds an observer to this object.
* @param callable $observer
* @return Observable
*/
public function addObserver(callable $observer)
{
$this->observers[] = $observer;
return $this;
}
/**
* If this object has changed, then notify all of the observers.
*/
protected function _notifyObservers()
{
foreach ( $this->observers as $observer )
{
call_user_func($observer, $this);
}
}
}
ためしに、エラー発生時に通知する仕組みをObserverでやるとこんな感じ。
Observerとしてロガーを渡すと幸せ。
ErrorHandler.php
<?php
class ErrorHandler
{
use Observable;
/**
* Register error handler.
* @return ErrorHandler
*/
public function register()
{
set_error_handler([$this, 'handleError'], E_ALL);
return $this;
}
/**
* Handle an error.
* @param int $severity
* @param string $message
* @param string $file
* @param int $line
* @return void
*/
public function handleError($severity, $message, $file, $line)
{
if ( ( $severity & error_reporting() ) != $severity )
{
return;
}
$this->_notifyObservers($severity, $message, $file, $line);
}
/**
* If this object has changed, then notify all of the observers.
* @param int $severity
* @param string $message
* @param string $file
* @param int $line
* @return Observable
*/
protected function _notifyObservers($severity, $message, $file, $line)
{
foreach ( $this->observers as $observer )
{
call_user_func($observer, $this);
}
}
<?php
$logger = function($severity, $message, $file, $line){
echo sprintf("%sの%u行目で、「%s」っていうエラーがレベル%uで発生したみたいだよ!", $file, $line, $message, $severity), PHP_EOL;
};
$errorHandler = new ErrorHandler();
$errorHandler->addObserver($logger)->register();