揭祕yii2中行為的方法是如何注入到元件類中去的~

阿北哥ya發表於2017-08-22

當了解了行為屬性的注入邏輯後,方法的注入對於我們來說就很簡單了。邏輯一樣。

只不過此刻我們不再呼叫 __get 方法,而是一個用於方法的 __call 方法。

在研究之前先根我學習兩個PHP的只是

  • __call
  • call_user_func_array

__call

__call 是 PHP 的一個魔術方法,這個方法和 __get 功能差不多,當發現一個類的方法未定義時會觸發此函式,它有兩個引數

public mixed __call ( string $name , array $arguments )複製程式碼

$name 引數是要呼叫的方法名稱。$arguments 引數是一個列舉陣列,包含著要傳遞給方法 $name 的引數,舉個例子

class User {
    public function __call($name, $arguments) {
            echo "Calling object method '$name' "
                 . implode(', ', $arguments). "\n";
    }
}

// do it
$model = new User();
$model->hello("abei2017");// Calling object method 'hello' abei2017複製程式碼

看懂了麼,貼個官方文件地址 傳送門

call_user_func_array

呼叫回撥函式,並把一個陣列引數作為回撥函式的引數。先貼個官方文件地址 傳送門 ,舉個例子再。

class User {
    function Hello($arg) {
        echo __METHOD__, " got $arg\n";
    }
}

$model = new User();
call_user_func_array([$model, "Hello"], ["abei2017"]); // User::Hello got abei2017複製程式碼

OK,在你瞭解了這兩個函式後,我們開始研究行為方法的注入。

方法如何注入

說來蠻簡單,就一個方法

// vendor/yiisoft/yii2/base/Component.php
public function __call($name, $params){

    $this->ensureBehaviors();
    foreach ($this->_behaviors as $object) {
        if ($object->hasMethod($name)) {
            return call_user_func_array([$object, $name], $params);
        }
    }
    throw new UnknownMethodException('Calling unknown method: ' . get_class($this) . "::$name()");
}複製程式碼

邏輯很簡單

  1. 使用 $this->ensureBehaviors(); 函式確保所有行為到位。
  2. 遍歷元件當前的行為,並判斷行為物件此方法是否存在。
  3. 如果存在則通過 call_user_func_array 呼叫此行為的方法

最後達到和元件呼叫自己的方法一樣的效果。

小結

到現在我們知道如何配置行為、行為執行、行為注入原理,下一篇我們將進行一個總結,把落下的比如解除行為操作說一下。


相關文章