Yii2 理解Component

简介: 版本继承与实现event和behaviorsbehaviors添加Behavior到ComponentensureBehaviorsattachBehavior和attachBehaviorsdetachBehavior和detachBehaviors__get__set__callon和off1 版本// yii\B

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分别是添加事件和移除事件

相关文章
|
16天前
Spartacus 2211 无法在文件夹下使用 ng g component 创建新的 Component
Spartacus 2211 无法在文件夹下使用 ng g component 创建新的 Component
7 0
Spartacus 2211 无法在文件夹下使用 ng g component 创建新的 Component
|
4月前
|
JavaScript 前端开发
vue-class-component
vue-class-component
39 1
|
Oracle 关系型数据库 MySQL
Yii2的基本要求是什么?
Yii2的基本要求是什么?
119 0
|
缓存 开发框架 安全
Yii2是什么?
Yii2是什么?
243 0
|
缓存 安全 数据处理
Yii2相对于Yii1有哪些改进?
Yii2相对于Yii1有哪些改进?
|
JavaScript 前端开发
Component初识组件
Component初识组件
91 0
SAP Spartacus component-wrapper自定义指令的实现
SAP Spartacus component-wrapper自定义指令的实现
SAP Spartacus component-wrapper自定义指令的实现
|
前端开发
SAP UI5 Web Component React应用如何在Component之间跳转
SAP UI5 Web Component React应用如何在Component之间跳转
123 0
SAP UI5 Web Component React应用如何在Component之间跳转
SAP UI5 component.js createContent
Created by Wang, Jerry, last modified on Mar 23, 2015
102 0
SAP UI5 component.js createContent