您现在的位置:首页 >> 前端 >> 内容

Yii2理解Component

时间:2017/1/7 9:23:00 点击:

  核心提示:Yii2理解Component。继承与实现 event和behaviors behaviors 添加Behavior到Component ensureBehaviors attachBehavior和...

Yii2理解Component。继承与实现 event和behaviors behaviors 添加Behavior到Component ensureBehaviors attachBehavior和attachBehaviors detachBehavior和detachBehaviors __get __set on和off

1 继承与实现

Component继承与Object, Object实现了Configurable接口, 该接口要求在函数参数列表末尾加上 $config

public function __construct($config = [])
{
    if (!empty($config)) 
    {
        Yii::configure($this, $config);
    }
    $this->init();
}

2 event和behaviors

private $_events = [];
private $_behaviors;

该类的重点就是事件(class Event)和行为(class Behavior)

3 behaviors()

public function behaviors()
{
    return [];
}

Component的派生类如果有需要使用到Behavior, 就需要重载这个函数。
比如Controller设置规则。

4 添加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;
}

5 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中

6 attachBehavior和attachBehaviors

这两个函数用于额外再添加行为

7 detachBehavior和detachBehaviors

这两个函数用于移除行为

8 __get

Component重写了__get函数, 这里就是将Behavior中的属性绑定到Component的地方

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;
            }
        }
    }
    ...
}

9 __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;
            }
        }
    }
    ...
}

10 on和off

on 和 off分别是添加事件和移除事件

Tags:YI II I2 2理 
作者:网络 来源:alex_my