Yii中的核心CComponent类详解


作者: 时间:2011-12-20

  

一本书最好的并不是它包含的思惟,而是它提出的思惟正如音乐的美好并不寄寓于它的调子,而在于我们心中的回响。CComponet类是Yii中影响最广的类。不仅Application持续自它,Event,Behavior,Action,Controller,Widget总之很多都是持续自它。在这里我们不一一列举,到底有哪些类是持续字CComponent类的。我们在这里主如果从实际意义上来解析CComponet的感化,角色。当读完本篇后,你应当对持续自Yii的CComponent的类有什么样的属性,什么样的特点和感化,了然于胸。

为了在生活生计中尽力阐扬本身的感化,酷爱人生吧。CComponent类是一个很重大的类,我们就遵守由粗到细的过程来讲解。让我们先直观感触感染下CComponet类是长什么样子的。

下图为CComponet的类视图

在申明这个类前,我们先简单介绍下php中几个首要的函数,在yii中,他们被频繁的应用。

__set() is run when writing data to inaccessible properties.

__get() is utilized for reading data inaccessible properties.

__isset() is triggered by calling isset() or empty() on inaccessible properties.

__unset() is invoked when unset() is used on inaccessible properties.

__call() is triggered when invoking inaccessible methods in an object context.

__callStatic() is triggered when invoking inaccessible methods in a static context.

上方是总php.net复制过来的,这里的英文都很简单,这里最关键的是要重视inaccessible这个字眼。

不过,为了下面能讲解的更顺畅,我捎带申明下吧。

__set默示,当以¥obj->variable=value这种情势保存值时,若是当这个variable不是class的属性时,也就是压根没有定义时,就会运行__set办法。那么有什么用呢?如许我们可以哄骗这个特点,捏造出很多属性来,比如这里,variable固然不存在,然则当他履行这个__set函数的时辰,我可以让其运行另一个函数,来获取对应的数值。是以,也可以借由这个来隐含应用setter。如许无论在应用便捷性上,还是安然性上都邑更好。

__get默示,当以¥obj->variable这种情势获取值时辰,若是当这个variable不是class的属性时,也就是压根没有定义时,就会运行__get办法。这个特点常备用来封装getter,具体的类似__set中的讲解。

__isset默示,当以isset(¥obj->variable)这种体式格式验证时辰,若是当这个variable不是class的属性时,也就是压根没有定义时,就会运行__isset办法,重视此时不会再运行__get办法了。因为运行__get办法就底子不是变量行动了。有悖于isset的初志。

__unset正好是__isset的逆向,这里就偷个懒不说了然,然则重视也不会运行__get。

__call默示,当以¥obj->method()这种情势进行函数调用时,若是这个method不存在,那么就会调用__call办法。

__callStatic,当以¥obj::method()这种情势进行函数调用时,若是这个method不存在,那么就会调用__callStatic办法。

Ok讲解完了,让我们言归正传。想要整体把握,须要深切懂得CComponet中的__call,__get,__isset,__set,__unset办法。

接下来,让我们逐个分化。

__set                                                            

 1     public function __set(¥name¥value
2 {
3 ¥setter=""set"".¥name;
4 ifmethod_exists¥this¥setter))
5 return ¥this->¥setter¥value);
6 else ifstrncasecmp¥name,""on"",2)===0 && method_exists¥this¥name))
7 {
8 // duplicating getEventHandlers() here for performance
9 ¥name=strtolower¥name);
10 if(!isset¥this->_e[¥name]))
11 ¥this->_e[¥name]=new CList;
12 return ¥this->_e[¥name]->add(¥value);
13 }
14 else ifis_array¥this->_m))
15 {
16 foreach¥this->_m as ¥object
17 {
18 if¥object->getEnabled() && (property_exists(¥object¥name) || ¥object->canSetProperty(¥name)))
19 return ¥object->¥name=¥value;
20 }
21 }
22 ifmethod_exists¥this,""get"".¥name))
23 throw new CException(Yii::t(""yii"",""Property "{class}.{property}" is read only."",
24 array(""{class}""=>get_class¥this), ""{property}""=>¥name)));
25 else
26 throw new CException(Yii::t(""yii"",""Property "{class}.{property}" is not defined."",
27 array(""{class}""=>get_class¥this), ""{property}""=>¥name)));
28 }

起首这个函数分4大块,分别为4-5行,6-13行,14-21行,22-27行,每一块都有特别的感化。

起首看4-5行,这里是看是否存在响应的setter(就是以set开首的,比如setComponents之类的),有的话则履行这个setter。

然后是6-13行,这个是专门为Yii的Event机制供给的,若是以on开首并且定义了同名的办法时,会履行此段。这里的函数体,实现了,即便你没有在类中定义形如onClick如许的属性,还是可以写入的。首要感化是当钱定义了Event后,将对应的EventHandler导入¥_e变量。这里涉及到你须要对Event有必然的懂得,若是不太懂得的,推荐浏览Yii中的Event和Behaviour懂得。

Ok,重视了,要记住¥_e是用来存放event Handler的并且是个CList(其实可以认为是一个Array)。

再看14-21行,当¥_m是个数组时,会遍历¥_m中的条目,这里插播一下,¥_m是什么?他其实就是一个装着Behavior的数组。那么为什么要断定起是不是数组,因为只有当是数组的时辰,才申明里面存在Behavior。插播停止,这就回来。我们接着看代码,遍历操纵将存在¥_m中的Behavior取了出来,当behavior必须启用,同时还要满足这个behavior类中存在须要写入的属性(这个属性可是实际存在的),若是不满足这个则须要满足这个behaivor中存在这个属性名对应的setter。当满足这些前提后,就申明可以经由过程¥object->¥name体式格式接见到,所以运行。

最后看22-27行,这项目组只是报错用的。当存在getter时辰,就提示read only。当不存在getter时,就提示not defined。

好了,落成一个__set了,后面可比这个轻松多了,因为很多根蒂根基在这里讲掉了,所以,不消愁闷后面路漫漫。

__get                                                               

 1 public function __get(¥name
2 {
3 ¥getter=""get"".¥name;
4 ifmethod_exists¥this¥getter))
5 return ¥this->¥getter();
6 else ifstrncasecmp¥name,""on"",2)===0 && method_exists¥this¥name))
7 {
8 // duplicating getEventHandlers() here for performance
9 ¥name=strtolower¥name);
10 if(!isset¥this->_e[¥name]))
11 ¥this->_e[¥name]=new CList;
12 return ¥this->_e[¥name];
13 }
14 else ifisset¥this->_m[¥name]))
15 return ¥this->_m[¥name];
16 else ifis_array¥this->_m))
17 {
18 foreach¥this->_m as ¥object
19 {
20 if¥object->getEnabled() && (property_exists(¥object¥name) || ¥object->canGetProperty(¥name)))
21 return ¥object->¥name;
22 }
23 }
24 throw new CException(Yii::t(""yii"",""Property "{class}.{property}" is not defined."",
25 array(""{class}""=>get_class¥this), ""{property}""=>¥name)));
26 }

有了__set的解析,这里就会很多,这里是5块,比__set多的一块,是用来获取behaivor的。咦,那为什么__set中没有写入behavior的操纵?为了更好的语义,在yii中选择没有写入behavior这个概念,只能经由过程attach,所以你要attach一个behavior,就用attachBehavior。熟悉打听了,这点,让我们持续看代码,这5块分别为,4-5行,6-13行,14-15行,16-23行,24-25行。

4-5行:看有没有getter,有的话就运行getter。

6-13行:若是是on开首的话,就返回¥_e中对应的项,若是没有就初始化一个CList并传回。

14-15行:若是在¥_m中存在雷同名称的内容,就返回之。(这个就是返回behavior的那个)。

16-23行:此处的断定和__set的14-21行的景象极其类似。在这里就不久不多解析了。

24-25行:异常处理惩罚。
__isset                                                              

 1     public function __isset(¥name
2 {
3 ¥getter=""get"".¥name;
4 ifmethod_exists¥this¥getter))
5 return ¥this->¥getter()!==null;
6 else ifstrncasecmp¥name,""on"",2)===0 && method_exists¥this¥name))
7 {
8 ¥name=strtolower¥name);
9 return isset¥this->_e[¥name]) && ¥this->_e[¥name]->getCount();
10 }
11 else ifis_array¥this->_m))
12 {
13 ifisset¥this->_m[¥name]))
14 return true;
15 foreach¥this->_m as ¥object
16 {
17 if¥object->getEnabled() && (property_exists(¥object¥name) || ¥object->canGetProperty(¥name)))
18 return true;
19 }
20 }
21 return false;
22 }

本来在PHP中isset主如果用于对变量是否存在作断定的,在这里yii将其的应用局限扩大了。感触感染更贴切的说isset变成了一个断定是否存在响应的getter(4-5行),对应的Event Handler是否含有真正的handler(6-10行),对应的behavior是否存在(11-20行)。这里须要重视下15-19行,这里使得,不仅仅可以断定behavior本身,包含其所属的属性和getter办法也是可以断定是否存在的。简单的懂得就是当isset感化于不存在的属性时,其变成了一个断定是否存在getter,event handler,behavior的办法。

__unset                                                              

 1     public function __unset(¥name
2 {
3 ¥setter=""set"".¥name;
4 ifmethod_exists¥this¥setter))
5 ¥this->¥setternull);
6 else ifstrncasecmp¥name,""on"",2)===0 && method_exists¥this¥name))
7 unset¥this->_e[strtolower¥name)]);
8 else ifis_array¥this->_m))
9 {
10 ifisset¥this->_m[¥name]))
11 ¥this->detachBehavior(¥name);
12 else
13 {
14 foreach¥this->_m as ¥object
15 {
16 if¥object->getEnabled())
17 {
18 if(property_exists(¥object¥name))
19 return ¥object->¥name=null;
20 else if¥object->canSetProperty(¥name))
21 return ¥object->¥setternull);
22 }
23 }
24 }
25 }
26 else ifmethod_exists¥this,""get"".¥name))
27 throw new CException(Yii::t(""yii"",""Property "{class}.{property}" is read only."",
28 array(""{class}""=>get_class¥this), ""{property}""=>¥name)));
29 }

unset的感化就是开释资料,懂得了unset的目标,我们可以看看__unset做了哪些,

4-5行:当有setter存在的时辰,

 

 

 

 

 

 

 

 

 

 

 1     public function __call(¥name¥parameters
2 {
3 if¥this->_m!==null
4 {
5 foreach¥this->_m as ¥object
6 {
7 if¥object->getEnabled() && method_exists¥object¥name))
8 return call_user_func_arrayarray¥object¥name),¥parameters);
9 }
10 }
11 ifclass_exists(""Closure"", false) && ¥this->canGetProperty(¥name) && ¥this->¥name instanceof Closure)
12 return call_user_func_array¥this->¥name¥parameters);
13 throw new CException(Yii::t(""yii"",""{class} and its behaviors do not have a method or closure named "{name}"."",
14 array(""{class}""=>get_class¥this), ""{name}""=>¥name)));
15 }

这段代码,起首断定了¥_m是不是为空,这个¥_m

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值