C#-like cобытия для PHP. Reflection, closures…

Posted by Olegas on Июнь 27, 2009
IT

Задача – сделать на 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));

Tags: , ,

1 комментарий to C#-like cобытия для PHP. Reflection, closures…

ingeceper
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]

Оставить комментарий

WP_Big_City