Yii源码阅读笔记(七)
接上次的组件(component)代码:
/**
* Returns a list of behaviors that this component should behave as.
* 定义该对象中要用到的 behavior,返回一个行为列表
* Child classes may override this method to specify the behaviors they want to behave as.
*
* 行为配置数组格式如下:
*
* ```php
* 'behaviorName' => [
* 'class' => 'BehaviorClass',
* 'property1' => 'value1',
* 'property2' => 'value2',
* ]
* ```
* Behaviors declared in this method will be attached to the component automatically (on demand).
* 定义该对象中要用到的 behavior
* @return array 行为配置.
*/
public function behaviors()
{
return [];
}
/**
* Returns a value indicating whether there is any handler attached to the named event.
* 判断 _events 中的一个 event 是否具有事件处理程序
* @param string $name 事件名
* @return boolean whether there is any handler attached to the event.
*/
public function hasEventHandlers($name)
{
$this->ensureBehaviors();
//短路写法,判断调用_events中是否有$name事件,没有直接返回false,否则,调用Event类中的的方法判断是否有处理程序
return !empty($this->_events[$name]) || Event::hasHandlers($this, $name);
}
/**
* Attaches an event handler to an event.
* 添加事件处理程序到事件
* The event handler must be a valid PHP callback. The following are
* some examples:
* 事件处理程序必须是有效的PHP回调函数,方便内置方法call_user_fucn()调用 ,例如:
* ```
* function ($event) { ... } // 匿名函数
* [$object, 'handleClick'] // 以数组形式表示的对象的方法
* ['Page', 'handleClick'] // 静态方法
* 'handleClick' // 全局函数,只写函数名
* ```
*
* The event handler must be defined with the following signature,
* 时间处理程序的定义格式:
* ```
* function ($event)
* ```
*
* where `$event` is an [[Event]] object which includes parameters associated with the event.
* `$event`是一个包含于event相关联的[[Event]]对象
* @param string $name 事件名
* @param callable $handler 事件处理函数
* @param mixed $data the data to be passed to the event handler when the event is triggered.
* When the event handler is invoked, this data can be accessed via [[Event::data]].
* @param boolean $append whether to append new event handler to the end of the existing
* handler list. If false, the new handler will be inserted at the beginning of the existing
* handler list.
* @see off()
*/
public function on($name, $handler, $data = null, $append = true)
{
$this->ensureBehaviors();//确保所有的行为都加载到组件中
if ($append || empty($this->_events[$name])) {//$append 判断是否添加到事件(event)的后面,且确保_events中有该事件
$this->_events[$name][] = [$handler, $data];//将事件处理程序和参数添加到event数组中
} else {//否则,添加到event数组的前面
array_unshift($this->_events[$name], [$handler, $data]);
}
}
/**
* Detaches an existing event handler from this component.
* This method is the opposite of [[on()]].
*
* [[on()]]方法的反方法,用于删除事件处理程序
*
* @param string $name 事件名
* @param callable $handler 事件处理程序
* 如果$handler 为空,清除该事件的所有时间处理程序
* @return boolean if a handler is found and detached
* @see on()
*/
public function off($name, $handler = null)
{
$this->ensureBehaviors();//确保所有的行为都加载到组件中
if (empty($this->_events[$name])) {//如果_events中没有该事件,也就是事件不存在
return false; //返回false
}
if ($handler === null) {//如果事件处理程序为空
unset($this->_events[$name]);//清除该事件的所有事件处理程序
return true; //返回true
} else {
$removed = false; //删除标记
//否则遍历该事件 根据on()方法的格式可以知道,$event[0]是事件处理程序,$event[1]是数据
foreach ($this->_events[$name] as $i => $event) {
if ($event[0] === $handler) {//判断事件处理程序是否符合
unset($this->_events[$name][$i]);//删除该事件处理程序
$removed = true;
}
}
if ($removed) {//判断是否删除成功
//如果删除成功,调用array_values方法重新赋值,格式化索引
$this->_events[$name] = array_values($this->_events[$name]);
}
return $removed;//返回删除成功标记
}
}
/**
* Triggers an event.
* This method represents the happening of an event. It invokes
* all attached handlers for the event including class-level handlers.
*
* 触发器方法
*
* @param string $name 事件名
* @param Event $event 事件参数. 如果未设置,一个默认的 [[Event]] 对象将被创建.
*/
public function trigger($name, Event $event = null)
{
$this->ensureBehaviors();
if (!empty($this->_events[$name])) {
if ($event === null) {
// 构建Event对象,为传入到handler函数中做准备
$event = new Event;
}
if ($event->sender === null) {
$event->sender = $this;
}
$event->handled = false;
$event->name = $name;
foreach ($this->_events[$name] as $handler) {
//遍历_events取得处理程序名和数据
$event->data = $handler[1];//给[[Event]] 的data属性赋值
call_user_func($handler[0], $event);//通过内置函数call_user_func()调用事件处理函数,$event作为参数
// stop further handling if the event is handled
// 事件是否被handle,当handled被设置为true时,执行到这个event的时候,会停止,并忽略剩下的event--不太明白,以后追加吧
if ($event->handled) {
return;
}
}
}
// invoke class-level attached handlers
//[[Event]] 的静态方法,触发类级别的事件处理程序
Event::trigger($this, $name, $event);
}
/**
* Returns the named behavior object.
* 获取行为类
* @param string $name the behavior name
* @return null|Behavior the behavior object, or null if the behavior does not exist
*/
public function getBehavior($name)
{
$this->ensureBehaviors();
return isset($this->_behaviors[$name]) ? $this->_behaviors[$name] : null;//_behaviors中的行为类存在,返回行为类名,否则返回空
}
/**
* Returns all behaviors attached to this component.
*
* 获取所有的行为类
* @return Behavior[] list of behaviors attached to this component
*/
public function getBehaviors()
{
$this->ensureBehaviors();
return $this->_behaviors;//直接返回了_behaviors
}
/**
* Attaches a behavior to this component.
* 添加一个行为到组件
* 通过提供的配置文件创建一个Behavior对象,通过调用 [[Behavior::attach()]] 方法添加行为到组件.
* @param string $name the name of the behavior.
* @param string|array|Behavior $behavior 行为配置,可选项如下:
*
* - 一个行为类
* - 一个字符串形式的指定行为类
* - 一个配置文件数组,通过调用[[Yii::createObject()]] 创建一个行为对象.
*
* @return Behavior the behavior object
* @see detachBehavior()
*/
public function attachBehavior($name, $behavior)
{
$this->ensureBehaviors();
return $this->attachBehaviorInternal($name, $behavior);
}
/**
* Attaches a list of behaviors to the component.
* 添加行为到组件
* 行为类通过行为名索引,且必须是一个 [[Behavior]] 对象指定的行为类或者一个配置数组
*
* @param array $behaviors list of behaviors to be attached to the component
* @see attachBehavior()
*/
public function attachBehaviors($behaviors)
{
$this->ensureBehaviors();
foreach ($behaviors as $name => $behavior) {
$this->attachBehaviorInternal($name, $behavior);
}
}
/**
* Detaches a behavior from the component.
* 从组件解除行为
* The behavior's [[Behavior::detach()]] method will be invoked.
* 实现方式是调用Behavior类中的detach()方法
* @param string $name the behavior's name.
* @return null|Behavior the detached behavior. Null if the behavior does not exist.
*/
public function detachBehavior($name)
{
$this->ensureBehaviors();
if (isset($this->_behaviors[$name])) {
$behavior = $this->_behaviors[$name];
unset($this->_behaviors[$name]);
$behavior->detach();
return $behavior;
} else {
return null;
}
}
/**
* Detaches all behaviors from the component.
* 解除所有的行为
*/
public function detachBehaviors()
{
$this->ensureBehaviors();
foreach ($this->_behaviors as $name => $behavior) {
$this->detachBehavior($name);
}
}
/**
* Makes sure that the behaviors declared in [[behaviors()]] are attached to this component.
* 确保定义的行为都被添加到组件
*/
public function ensureBehaviors()
{
if ($this->_behaviors === null) {// 如果$this->_behaviors为空
$this->_behaviors = [];
foreach ($this->behaviors() as $name => $behavior) {//遍历$this->behaviors()中的behaviors,并存储到$this->_behaviors数组中
$this->attachBehaviorInternal($name, $behavior);
}
}
}
/**
* Attaches a behavior to this component.
* 私有方法 添加一个行为到组件
* @param string|integer $name 行为名. 如果是整数,说明该行为是匿名的
* @param string|array|Behavior $behavior the behavior to be attached
* @return Behavior the attached behavior.
*/
private function attachBehaviorInternal($name, $behavior)
{
if (!($behavior instanceof Behavior)) {
// $behavior不是Behavior对象,就认为是配置,通过它创建一个
$behavior = Yii::createObject($behavior);
}
if (is_int($name)) {//行为名师整数
$behavior->attach($this);//绑定行为到组件
$this->_behaviors[] = $behavior;
} else {
if (isset($this->_behaviors[$name])) {
// 如果有同名的行为存在就先解绑掉
$this->_behaviors[$name]->detach();
}
$behavior->attach($this);//重新绑定行为到组件
$this->_behaviors[$name] = $behavior;
}
return $behavior;
}
Yii源码阅读笔记(七)的更多相关文章
- Yii源码阅读笔记(一)
今天开始阅读yii2的源码,想深入了解一下yii框架的工作原理,同时学习一下优秀的编码规范和风格.在此记录一下阅读中的小心得. 每个框架都有一个入口文件,首先从入口文件开始,yii2的入口文件位于we ...
- Yii源码阅读笔记(八)
前面阅读了Yii2的两个基本类Object和Component,了解了Yii的三个重要概念属性.事件.行为,下面开始阅读Event类,Event类是所有事件类的基类: <?php /** * @ ...
- Yii源码阅读笔记(三)
接着上次的继续阅读BaseYii.php vendor/yiisoft/yii2/BaseYii.php—— public static function getRootAlias($alias)// ...
- Yii源码阅读笔记(二)
接下来阅读BaseYii.php vendor/yiisoft/yii2/BaseYii.php—— namespace yii; use yii\base\InvalidConfigExceptio ...
- Yii源码阅读笔记(三十五)
Container,用于动态地创建.注入依赖单元,映射依赖关系等功能,减少了许多代码量,降低代码耦合程度,提高项目的可维护性. namespace yii\di; use ReflectionClas ...
- Yii源码阅读笔记(三十四)
Instance类, 表示依赖注入容器或服务定位器中对某一个对象的引用 namespace yii\di; use Yii; use yii\base\InvalidConfigException; ...
- Yii源码阅读笔记(三十三)
ServiceLocator,服务定位类,用于yii2中的依赖注入,通过以ID为索引的方式缓存服务或则组件的实例来定位服务或者组件: namespace yii\di; use Yii; use Cl ...
- Yii源码阅读笔记(三十二)
web/Application类的注释,继承base/Application类,针对web应用的一些处理: namespace yii\web; use Yii; use yii\base\Inval ...
- Yii源码阅读笔记(三十一)
Widget类中开始,获取视图对象,获取widget ID,渲染视图,获取路径方法注释: private $_id; /** * Returns the ID of the widget. * 返回插 ...
随机推荐
- Redis、Memcache和MongoDB的区别
>>Memcached Memcached的优点:Memcached可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS(取决于key.value的字节大小以及服务器硬件性能,日常环境 ...
- 【转】解决编译Apache出现的问题:configure: error: APR not found . Please read the documentation
这里写的很清楚了,已验证可用 http://blog.csdn.net/linghao00/article/details/7926458
- hdu 1286:找新朋友(数论,欧拉函数)
找新朋友 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- 浅谈K-SVD
由于工作需要,最近刚刚看了一些K-SVD的介绍,这里给自己做一下小节. K-SVD我们一般是用在字典学习.稀疏编码方面,它可以认为是K-means的一种扩展,http://en.wikipedia.o ...
- C++的那些事:const用法面面观
一.const是什么 在 C/C++ 语言中,const关键字是一种修饰符.所谓“修饰符”,就是在编译器进行编译的过程中,给编译器一些“要求”或“提示”,但修饰符本身,并不产生任何实际代码.就 con ...
- OD使用心得
查看堆栈 从返回前面的竖线 到 竖线结束 也就是到 (从返回 msconfig.0065a318) 全看.这样不会丢失些东西 或者 看堆栈 直接将堆栈框拉大 避免有些东西没有看到
- aggregateByKey
def seq(a:Int, b:Int) : Int ={ math.max(a,b) } def comb(a:Int, b:Int) : Int ={ a + b } val data = sc ...
- Hark的数据结构与算法练习之桶排序
算法说明 桶排序的逻辑其实特别好理解,它是一种纯粹的分而治之的排序方法. 举个例子简单说一下大家就知道精髓了. 假如对11,4,2,13,22,24,20 进行排序. 那么,我们将4和2放在一起,将1 ...
- HDU3996 Gold Mine(最大权闭合子图)
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> using ...
- Viola Jones Face Detector
Viola Jones Face Detector是Paul viola 和 Michael J Jones共同提出的一种人脸检测框架.它极大的提高了人脸检测的速度和准确率. 速度提升方面:利用积分图 ...