1 版本
// yii\BaseYii\getVersion
public static function getVersion()
{
return '2.0.10';
}
2 继承与实现
Component继承与Object, Object实现了Configurable接口, 该接口要求在函数参数列表末尾加上 $config
public function __construct($config = [])
{
if (!empty($config))
{
Yii::configure($this, $config);
}
$this->init();
}
3 event和behaviors
private $_events = [];
private $_behaviors;
该类的重点就是事件(class Event)和行为(class Behavior)
4 behaviors()
public function behaviors()
{
return [];
}
Component的派生类如果有需要使用到Behavior, 就需要重载这个函数。
比如Controller设置规则。
5 添加Behavior到Component
private function attachBehaviorInternal($name, $behavior)
{
if (!($behavior instanceof 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;
}
6 ensureBehaviors
Component将会在很多地方调用该函数, 确保行为被添加到该组件中
public function ensureBehaviors()
{
if ($this->_behaviors === null)
{
$this->_behaviors = [];
foreach ($this->behaviors() as $name => $behavior)
{
$this->attachBehaviorInternal($name, $behavior);
}
}
}
假设XXController::behaviors()定义如下:
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
public function behaviors()
{
return [
// 指定了行为名称
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['login', 'error', 'register'],
'allow' => true,
],
[
'allow' => true,
'roles' => ['@'],
]
]
],
// 未指定行为名称
[
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
'delete' => ['post'],
'upload'=>['post'],
]
]
];
}
一个是命名为access的行为, 一个是匿名行为。
将其打印输出:
array(2) {
// --------------------- access行为
["access"]=>
array(2) {
["class"]=>
string(25) "yii\filters\AccessControl"
["rules"]=>
array(2) {
[0]=>
array(2) {
["actions"]=>
array(3) {
[0]=>
string(5) "login"
[1]=>
string(5) "error"
[2]=>
string(8) "register"
}
["allow"]=>
bool(true)
}
[1]=>
array(2) {
["allow"]=>
bool(true)
["roles"]=>
array(1) {
[0]=>
string(1) "@"
}
}
}
}
// --------------------- 数字表示匿名行为
[0]=>
array(2) {
["class"]=>
string(22) "yii\filters\VerbFilter"
["actions"]=>
array(3) {
["logout"]=>
array(1) {
[0]=>
string(4) "post"
}
["delete"]=>
array(1) {
[0]=>
string(4) "post"
}
["upload"]=>
array(1) {
[0]=>
string(4) "post"
}
}
}
}
两个行为会通过attachBehaviorInternal添加到Component中
7 attachBehavior和attachBehaviors
这两个函数用于额外再添加行为
8 detachBehavior和detachBehaviors
这两个函数用于移除行为
9 __get
Component重写了__get函数, 这里就是将Behavior中的属性绑定到Component的地方,这样Component就可以像调用自身属性一样调用Behavior中的属性
public function __get($name)
{
$getter = 'get' . $name;
// 如果能在Component中找到该属性, 则返回该属性的值
if (method_exists($this, $getter))
{
return $this->$getter();
}
else
{
// 确保行为都绑定了
$this->ensureBehaviors();
// 如果能在各个Behavior中找到该属性,则调用Behavior中的值
foreach ($this->_behaviors as $behavior)
{
if ($behavior->canGetProperty($name))
{
return $behavior->$name;
}
}
}
...
}
10 __set
Component重写了__set函数
public function __set($name, $value)
{
$setter = 'set' . $name;
if (method_exists($this, $setter))
{
$this->$setter($value);
return;
}
// 如果以'on '开头则认为是添加事件
elseif (strncmp($name, 'on ', 3) === 0)
{
// 截取第3个元素之后的字符串, 做为事件名称
$this->on(trim(substr($name, 3)), $value);
return;
}
// 如果以'as '开头则认为是添加行为
elseif (strncmp($name, 'as ', 3) === 0)
{
// 截取第3个元素之后的字符串, 做为行为名称
$name = trim(substr($name, 3));
$this->attachBehavior($name, $value instanceof Behavior ? $value : Yii::createObject($value));
return;
}
else
{
// behavior property
$this->ensureBehaviors();
foreach ($this->_behaviors as $behavior)
{
if ($behavior->canSetProperty($name))
{
$behavior->$name = $value;
return;
}
}
}
...
}
11 __call
这里就是将Behavior中的函数绑定到Component的地方,这样Component就可以像调用自身函数一样调用Behavior中的函数
public function __call($name, $params)
{
$this->ensureBehaviors();
foreach ($this->_behaviors as $object) {
if ($object->hasMethod($name)) {
return call_user_func_array([$object, $name], $params);
}
}
...
}
12 on和off
on 和 off分别是添加事件和移除事件