PHP 事件机制(2)

复制代码 代码如下:

  <?php

  class Event extends stdClass{

  public $target=null;

  public $type=null;

  /**

  * 创建事件

  * @param string $type

  */

  public function __construct($type){

  $this->type=trim($type);

  }

  /**

  * 得到事件字符串

  */

  public function __toString(){

  return $this->type;

  }

  }

  abstract class EventDispatcher{

  private $_callback_method;

  /**

  * 添加事件

  * @param Event $event

  * @param string $method

  * @param string||object $class

  * @return boolean true

  */

  public function attach($event,$method,$class=null){

  $eventstr=(string)$event;

  if($this->has($event,$method,$class))

  return true;

  if($class!=null){

  $this->_check_method($class,$method);

  $this->_callback_method[$eventstr][]=$this->_create_listener_method($eventstr,$class,$method);

  }else{

  $this->_check_function($method);

  $this->_callback_method[$eventstr][]=$this->_create_listener_fn($eventstr,$method);

  }

  return true;

  }

  /**

  * 派发事件

  * @param Event $event

  * @param string $method

  * @param string||object $class

  * @return void

  */

  public function dispatch(Event $event){

  $event->target=$this;

  $eventstr=(string)$event;

  if($this->_check_callback($eventstr)){

  foreach ($this->_callback_method[$eventstr] as $v){

  if($v['object']){

  if(is_object($v['class'])){

  $v['class']->$v['method']($event);

  }else{

  call_user_func(array($v['class'], $v['method']),$event);

  }

  }else{

  $v['function']($event);

  }

  }

  }

  }

  /**

  * 删除事件

  * @param Event $event

  * @param string $method

  * @param string $class

  * @return boolean true

  */

  public function detact($event,$method,$class=null){

  $eventstr=(string)$event;

  if(!$this->_check_callback($eventstr))

  return true;

  if(!$this->has($event,$method,$class))

  return true;

  if($class!=null){

  $this->_check_method($class,$method);

  foreach ($this->_callback_method[$eventstr] as $k=>$v) {

  if(($v==$this->_create_listener_method($eventstr,$class,$method))){

  unset($this->_callback_method[$eventstr][$k]);

  return true;

  }

  }

  return true;

  }else{

  $this->_check_function($method);

  foreach ($this->_callback_method[$eventstr] as $k=>$v) {

  if(($v==$this->_create_listener_fn($eventstr,$method))){

  unset($this->_callback_method[$eventstr][$k]);

  return true;

  }

  }

  return true;

  }

  }

  /**

  * 检测事件是否监听

  * @param Event $event

  * @param string $method

  * @param string $class

  * @return boolean

  */

  public function has($event,$method,$class=null){

  $eventstr=(string)$event;

  if(($class!=null)){

  $this->_check_method($class,$method);

  if($this->_check_callback($eventstr)){

  foreach($this->_callback_method[$eventstr] as $v){

  if(is_object($v['class'])){

  $v_class=get_class($v['class']);

  }else{

  $v_class=$v['class'];

  }

  if(is_object($class)){

  $s_class=get_class($class);

  }else{

  $s_class=$class;

  }

  $temp_v=array(

  "class"=>$v_class,

  "method"=>$method,

  );

  $temp_s=array(

  "class"=>$s_class,

  "method"=>$method,

  );

  if($temp_v==$temp_s){

  return true;

  }

  }

  }

  }else{

  $this->_check_function($method);

  if($this->_check_callback($eventstr)){

  foreach($this->_callback_method[$eventstr] as $v){

  if($method==$v['function']){

  return true;

  }

  }

  }

  }

  return false;

  }

  /**

  * 检测指定类是否存在指定方法

  * @param string $class

  * @param string $method

  * @exception Exception_Event

  * @return void

  */

  private function _check_method($class,$method){

  if(!method_exists($class,$method)){

  throw new Exception(get_class($class)." not exist ".$method." method",1);

  }

  }

  /**

  * 检测指定函数是否存在

  * @param string $function

  * @return void

  */

  private function _check_function($function){

  if(!function_exists($function)){

  throw new Exception($function." function not exist ",2);

  }

  }

  /**

  * 检测指定事件是否存在监听函数

  * @param string $eventstr

  * @return boolean

  */

  private function _check_callback($eventstr){

  if(isset($this->_callback_method[$eventstr])

  &&is_array($this->_callback_method[$eventstr])

  ){

  return true;

  }

  return false;

  }

  /**

  * 创建监听函数数组

  * @param string $eventstr

  * @param string $function

  * @return array

  */

  private function _create_listener_fn($eventstr,$function){

  return array(

  "object"=>false,

  "function"=>$function,

  );

  }

  /**

  * 创建监听类数组

  * @param string $eventstr

  * @param string $class

  * @param string $method

  * @return array

  */

  private function _create_listener_method($eventstr,$class,$method){

  return array(

  "object"=>true,

  "class"=>$class,

  "method"=>$method,

  );

  }

  }

  class myevent extends Event{

  const aa='aaa';

  }

  class ball extends EventDispatcher{

  public function aa(){

  $event=new myevent(myevent::aa);

  $this->dispatch($event);

  }

  }

  class mytest {

  public function test(){

  $ball=new ball();

  $ball->attach(myevent::aa,'kk');

  $ball->aa();

  }

  public function kk($e){

  print_r($e);

  }

  }

  try{

  $t=new mytest();

  $t->test();

  }catch (Exception $e){

  echo $e->getmessage();

  }