博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
YII框架分析笔记2:组件和事件行为管理
阅读量:7095 次
发布时间:2019-06-28

本文共 3298 字,大约阅读时间需要 10 分钟。

Yii是一个基于组件、用于开发大型 Web 应用的高性能  框架。CComponent几乎是所有类的基类,它控制着组件与事件的管理,其方法与属性如下,私有变量$_e数据存放事件(evnet,有些地方叫hook),$_m数组存放行为(behavior)。

 

组件管理

YII是一个纯oop框架,很多类中的成员变量的受保护或者私有的,CComponent中利用php中的魔术方法__get(),__set()来访问和设置属性,但这些方法的作用远不指这些。下面用__get()来说明

public function __get($name)  {      $getter='get'.$name;      if(method_exists($this,$getter))          return $this->$getter();       else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name))      {          // duplicating getEventHandlers() here for performance          $name=strtolower($name);          if(!isset($this->_e[$name]))              $this->_e[$name]=new CList;          return $this->_e[$name];      }      else if(isset($this->_m[$name]))          return $this->_m[$name];      else if(is_array($this->_m))      {          foreach($this->_m as $object)          {              if($object->getEnabled() && (property_exists($object,$name) || $object->canGetProperty($name)))                  return $object->$name;          }      }      throw new CException(Yii::t('yii','Property "{class}.{property}" is not defined.',          array('{class}'=>get_class($this), '{property}'=>$name)));  }

当CComponent或者其子类对象实例$obj->name的时候,__get($name)方法:

1、首先判断实例中是否有getName()方法,如果有则返回 ,如果没有执行第2步
2、判断是否是以on开头的,以on开头的一般都是CComponent子类中预留的事件,用与挂在事件,通过method_exists($this,$name)判断该name是否存在类的实例中,如果存在,返回事件,否则执行第3步
3、如果name存在行为数组中,返回改行为,如果不存在,执行第4步
4、遍历行为数组,数组中行为是CBehavior子类的实例,而CBehavior又是CComponent中子类,所以用递归的方法获取行为中的方法,如果没有,执行第5步
5、抛出异常:请求的属性不存在。

在CComponent子类中可以重载__get()方法,如在CModule中加入了获取组件的判断。这就注意一个问题了属性和组件名最好不要重名,因为程序会优先加载组件,可能得到的不是我们想要的属性,如果必须重名的话,就要用getter获取属性。

public function __get($name)  {      if($this->hasComponent($name))          return $this->getComponent($name);      else          return parent::__get($name);  }

注册的时候只是把组件和其对应的配置用键值对的形式保存在数组中(预加载的除外),当用到时候才像上面那样去创建组件,会通过YIIBase中的createComponent()方法创建,并初始化。通过CModule或其子孙类(如CWebApplication)调用__get()或getComponent()获取组件时,CModule通过$_components数组建立对象池,确保每个组件在一次请求中只实例化一次。

 

事件行为管理

事件相当于对一个组件的扩展或者插件,以组件中预留的钩子实现组件内部调用外部、外部对组件部分控制。在CComponent子类中可以定义以on开头的方法为事件,类似于js中的onclick、onchange等,其实原理差不多。所有事件是与CComponent在同一文件中CEvent的子类。

/** * Raised right BEFORE the application processes the request. * @param CEvent $event the event parameter */  public function onBeginRequest($event)  {      $this->raiseEvent('onBeginRequest',$event);  }  /** * Runs the application. * This method loads static application components. Derived classes usually overrides this * method to do more application-specific tasks. * Remember to call the parent implementation so that static application components are loaded. */  public function run()  {      if($this->hasEventHandler('onBeginRequest'))          $this->onBeginRequest(new CEvent($this));      $this->processRequest();      if($this->hasEventHandler('onEndRequest'))          $this->onEndRequest(new CEvent($this));  }

比如在CApplication中调用run()方法在处理请求之前先判断外部是否传人onBeginRequest事件的句柄,如果有则通过onBeginRequest($event)方法调用CComponent中的raiseEvent()方法执行句柄中的函数或者方法。

行为是事件的升级版,所有的行为都是CBehavior的子类。分析上面的__get()方法分析第4步可以看出来行为的作用是完全扩展组件的特性,可以是属性、方法、事件甚至行为,这样使程序开发更加灵活。

行为的另一个作用是将相似事件句柄放在一起,在行为执行attach()方法的时候会将events()方法中返回的事件句柄绑定,这样做达到方面管理和扩展的目的。比如CModelBehavior中将model相关的事件集中起来,便于其子类的复用,当我们需求为model添加行为的时候可以继承它

原文来源http://blog.csdn.net/wzllai/article/details/7659008#

你可能感兴趣的文章
Java的集合类
查看>>
随机数
查看>>
PLSQL Developer 不能连接 oracle 12c 64位 的解决办法 for win 64
查看>>
Paxos算法与Zookeeper分析
查看>>
2018-2019-2 网络对抗技术 20165318 Exp 8 Web基础
查看>>
hotmail邮件中背景图片不显示的解决办法
查看>>
实习小白::(转) Cocos2d-x 3.0 开发(十四)使用UIScrollView 实现大小不同物品拖动展示...
查看>>
11.SpringMVC注解式开发-处理器方法的返回值
查看>>
Go 标准库 —— sync.Mutex 互斥锁
查看>>
Virtualbox-CentOS网络配置
查看>>
spring中方法级验证参数
查看>>
grpc测试
查看>>
eclipse快捷键整理
查看>>
Android studio 3.0安装MUMU模拟器
查看>>
selenium操作滚动条方法
查看>>
3、输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
查看>>
MyISAM InnoDB 区别
查看>>
时钟巡回
查看>>
看博客学学Android(六)
查看>>
Transformation functionality for the String class
查看>>