yii学习一:Object基类与component的特性

1、类的属性

Yii中为Object基类规定义了属性:属性支持get、set特性。

1.1getter特性和setter特性

继承yii\base\Object的类有一个public function getXxx()方法时,可以直接通过echo $obj->xxx来输出getXxx方法的返回值。

总结:关键是方法要public,然后是get开头,get后面的单词就是访问的属性名,方法不能有参数

当你定义了public function setAge($value)的时候,执行$obj->age = 9就会触发setAge($value)方法,而这个$value就是赋过来的值

总结:方法也要public,命名前缀则是set开头,接收一个$value参数处理等号赋的值

如果只提供了getter,那么该属性为只读属性,只提供了setter,则为只写。

1.2Object和Component

yii\base\Component 继承自 yii\base\Object ,因此,他也具有属性等基本功能。但是,由于Componet还引入了事件、行为,

因此,Component类具有三个重要的特性:

  • 属性(property)
  • 事件(event)
  • 行为(behavior)

1.3、Yii中就是统一使用数组的方式对对象进行配置

Application对象的配置就是这种配置方式的体现:

$config = yii\helpers\ArrayHelper::merge(
    require(__DIR__ . '/../../common/config/main.php'),
    require(__DIR__ . '/../../common/config/main-local.php'),
    require(__DIR__ . '/../config/main.php'),
    require(__DIR__ . '/../config/main-local.php')
);

$application = new yii\web\Application($config);

那是因为yii\base\Object 定义的构造函数中:

public function __construct($config = [])
{
    if (!empty($config)) {
        Yii::configure($this, $config);
    }
    $this->init();
}
  • 构建函数以 $config 数组为参数被自动调用。
  • 构建函数调用 Yii::configure() 对对象进行配置。
  • 在最后,构造函数调用对象的 init() 方法进行初始化。

Yii::configure可以将一个与类的属性名对应的数组值注入到类的属性中。原因在于:

public static function configure($object, $properties)
{
    foreach ($properties as $name => $value) {
        $object->$name = $value;
    }

    return $object;
}

1.4、可以在new的时候进行属性注入

namespace app;
class Test extends \yii\base\Object{
	public $name;	
	public $age;
}
//然后在控制器里看看效果
$config = [
	'name' => 'Jay',
	'age' => 26,
];
$test = new Test($config);
print_r([$test->name, $test->age]);

问题:如果配置数组的某个配置项,也是一个数组, 或者如果一个对象的属性,是另一个对象,这两种情况实质是一样的,嵌套配置数组,在Yii的配置文件中,可以看到一个配置项 components

'components' => [
    'request' => [       
        'cookieValidationKey' => 'v7mBbyetv4ls7t8UIqQ2IBO60jY_wf_U',
    ],
    'user' => [
        'identityClass' => 'common\models\User',
        'enableAutoLogin' => true,
    ],
    'log' => [
        'traceLevel' => YII_DEBUG ? 3 : 0,
        'targets' => [
            [
                'class' => 'yii\log\FileTarget',
                'levels' => ['error', 'warning'],
            ],
        ],
    ],
    'errorHandler' => [
        'errorAction' => 'site/error',
    ],
],

2、事件

1:事件既是代码解耦的一种方式,也是设计业务流程的一种模式,使用事件,可以在特定的时点,触发执行预先设定的一段代码。

2:Yii 中yii\base\Object 不支持事件。 如果一个类需要触发事件就应该继承 yii\base\Component 或其子类。

3:Yii中还有一个与事件紧密相关的 yii\base\Event ,他封装了与事件相关的有关数据,并提供一些功能函数作为辅助:

event类代码如下:

class Event extends Object
{
    public $name;               // 事件名
    public $sender;             // 事件发布者,通常是调用了 trigger() 的对象或类。
    public $handled = false;    // 是否终止事件的后续处理
    public $data;               // 事件相关数据

    private static $_events = [];

    public static function on($class, $name, $handler, $data = null,
        $append = true)
    {
        // ... ...
        // 用于绑定事件handler
    }

    public static function off($class, $name, $handler = null)
    {
        // ... ...
        // 用于取消事件handler绑定
    }

    public static function hasHandlers($class, $name)
    {
        // ... ...
        // 用于判断是否有相应的handler与事件对应
    }

    public static function trigger($class, $name, $event = null)
    {
        // ... ...
        // 用于触发事件
    }
}

2.1、事件handler

handler里就是写业务逻辑的地方了,对于一个事件handler,可以是以下的形式提供:

  • 一个PHP全局函数的函数名,不带参数和括号,光秃秃的就一个函数名。如 trim ,注意,不是 trim($str) 也不是 trim() 。
  • 一个对象的方法,或一个类的静态方法。如 $person->sayHello() 可以用为事件handler,但要改写成以数组的形式, [$person, 'sayHello'] ,而如果是类的静态方法,那应该是 ['namespace\to\Person', 'sayHello'] 。
  • 匿名函数。如 function ($event) { ... }

但无论是何种方式提供,一个事件handler必须具有以下形式:

function ($event) {
    // $event 就是前面提到的 yii\base\Event
}

————此处应该通过一个例子来解决事件的定义,绑定,接触,触发,等功能(未完,待续)————

3、行为(可以动态添加方法属性

1:使用行为(behavior)可以在不修改现有类的情况下,对类的功能进行扩充。 通过将行为绑定到一个类,可以使类具有行为本身所定义的属性和方法,就好像类本来就有这些属性和方法一样。 而且不需要写一个新的类去继承或包含现有类。

2:Yii中的行为,其实是 yii\base\Behavior 类的实例, 只要将一个Behavior实例绑定到任意的 yii\base\Component 实例上, 这个Component就可以拥有该Behavior所定义的属性和方法了。注意,Behavior只能与Component类绑定,所以,如果你写了一个类,需要使用到行为,那么就果断地继承自 yii\base\Component 。

3:这个与 object中数组进行属性注入是有区别的,区别在于使用行为时才会有这个属性,不使用时没有,而注入,则永远有这个属性。

3.1写一个行为代码:

class Behavior extends Object
{
    // 指向行为本身所绑定的Component对象
    public $owner;

    // Behavior 基类本身没用,主要是子类使用,重载这个函数返回一个数组表
    // 示行为所关联的事件
    public function events()
    {
        return [];
    }

    // 绑定行为到 $owner
    public function attach($owner)
    {
        ... ...
    }

    // 解除绑定
    public function detach()
    {
        ... ...
    }
}

3.2使用行为

一个绑定了行为的类,表现起来是这样的:

// Step 1: 定义一个将绑定行为的类
class MyClass extends yii\base\Component
{
    // 空的
}

// Step 2: 定义一个行为类,他将绑定到MyClass上
class MyBehavior extends yii\base\Behavior
{
    // 行为的一个属性
    public $property1 = 'This is property in MyBehavior.';

    // 行为的一个方法
    public function method1()
    {
        return 'Method in MyBehavior is called.';
    }
}

$myClass = new MyClass();
$myBehavior = new MyBehavior();

// Step 3: 将行为绑定到类上
$myClass->attachBehavior('myBehavior', $myBehavior);

// Step 4: 访问行为中的属性和方法,就和访问类自身的属性和方法一样
echo $myClass->property1;
echo $myClass->method1();

3.3行为的绑定

上例中绑定行为直接调用yii\base\Compoent::attachBehaviors(),这个是动态绑定的方法,还有个静态绑定方式:

静态绑定行为,只需要重载 yii\base\Component::behaviors() 就可以了。 这个方法用于描述类所具有的行为。如何描述呢? 使用配置来描述,可以是Behavior类名,也可以是Behavior类的配置数组:

————具体操作有待进一步理解——

3.4查看绑定好的行为

对于命名的行为,可以调用 yii\base\Component::getBehavior() 来取得这个绑定好的行为:

$behavior = $Component->getBehavior('myBehavior2');

对于匿名的行为,则没有办法直接引用了。但是,可以获取所有的绑定好的行为:

$behaviors = $Component->getBehaviors();

3.5解除行为

解除行为只需调用 yii\base\Component::detachBehavior() 就OK了:

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章