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了:

 

 

 

 

 

 

 

 

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