Задача – сделать на PHP эвенты а-ля C# т.е. произвольный объект может генерировать события. Другие объекты могут на эти события подписываться непосредственно у экземпляра генерирующего объекта.
abstract class EventClass {
/**
* Хранятся колбэки для событий
*
* @var array
*/
protected $eventRecievers = array();
/**
* События - массив строк
*
* @var array
*/
protected $myEvents = array();
/**
* Сеттер для событий
*
* @param string $prop Событие
* @param callback $val Колбэк
*/
function __set($prop, $val)
{
if(in_array($prop, $this->myEvents))
$this->attachEvent($prop, $val);
else
throw new Exception("Property {$prop} is not found or read only");
}
/**
* Caller overloader
*
* @param string $name Имя вызываемого метода
* @param array $args Массив аргументов
*/
function __call($name, $args)
{
if(in_array($name, $this->myEvents))
$this->fireEvent($name, current($args));
else
throw new Exception("No such event or bad arguments given");
}
/**
* Присоединяет хэндлер события к выбранному событию
*
* @param srting $event Событие
* @param callback $callback Колбэк
*/
protected function attachEvent($event, $callback)
{
if(in_array($event, $this->myEvents))
{
if(is_array($callback) && is_object($callback[0]) && is_string($callback[1]))
{
$reflection = new ReflectionClass(get_class($callback[0]));
try {
$method = $reflection->getMethod($callback[1]);
if($method->getNumberOfParameters() == 1)
$this->eventRecievers[$event][]=$callback;
else
throw new Exception(get_class($callback[0])."::{$callback[1]} have more than 1 arguments");
}
catch(Exception $e) {
throw new Exception("Class ".get_class($callback[0])." doesn't have method {$callback[1]}");
}
}
else
throw new Exception("Wrong callback format");
}
else
throw new Exception(__CLASS__." have no event {$event}");
}
/**
* "Зажигает" событие
*
* @param string $event
* @param EventArgument $argument
*/
protected function fireEvent($event, $argument)
{
if(in_array($event, $this->myEvents))
{
if(is_array($this->eventRecievers[$event]) && count($this->eventRecievers[$event]))
foreach($this->eventRecievers[$event] as $callback)
call_user_func_array($callback, array(new EventArgument($this, $argument)));
}
else
throw new Exception(__CLASS__." have no event {$event}");
}
}
class CanGenerateEvents extends EventClass {
protected $myEvents = array('onSomething', 'onSomethingElse');
// Code goes here
function makeSomething()
{
// Doing something useful...
$this->onSomething("someText");
}
}
class WantSomething {
function recieveHere(EventArgument $arg)
{
echo $arg->argument;
}
}
$w = new WantSomething();
$g = new CanGenerateEvents();
$g->onSomething = array($w, 'recieveHere');
Когда в PHP повится метод ReflectionMethod::getClosure() (который, судя по всему, не войдет в 5.3 хотя ранее присутствовал в документации) можно будет отказаться от использования call_user_func_array и использовать замыкания, заменив строку 63 на следующий код
$this->eventRecievers[$event][]=$method->getClosure();
А строку в функции fireEvent на следующее…
$callback(new EventArgument($this, $argument));

28.01.2012
[img]http://xn--80adheihowok.xn--p1ai/wp-content/uploads/2012/01/sms_ot_dedamoroza2.jpg[/img]
DedMoroz: Я предлагаю вам замечательный сервис по отправке [b]СМС от Деда Мороза[/b] и других сказочных героев. Ведь так приятно маленькой дочке или сыну, получить [b]СМС от деда мороза [/b]или Снегурочке. Или пообещать любимому человеку, что в наступающем новому году его будут окружать только близкие и преданные люди. Или написать СМС своим родителям, с красивыми и искренними пожеланиями и признаниями.
[b]СМС от Деда Мороза[/b] позволяет внести радость и счастье каждому человеку, вне зависимости от его возраста. Даже если праздники прошли, шампанское допито, елка убрана, то все равно приятно получить [b]SMS с новым годом[/b] в поддержку любимому и близкому человеку, [b]SMS от деда мороза[/b] всегда заставит улыбаться каждого человека.
[b]Перейти: [/b]http://впразднике.рф
[img]http://xn--80adheihowok.xn--p1ai/wp-content/uploads/2012/01/sms_ot_dedamoroza.jpg[/img]