談談thinkphp5.1中容器(Container)和門面(Facade)的實現【轉載】
阿新 • • 發佈:2019-02-02
// thinkphp\library\facade\Config 類
namespace think\facade;
use think\Facade;
class Config extends Facade
{
}
// 從原始碼上看 Config本身沒有任何方法,它繼承了Facade的方法,但Facade並沒有get這個靜態方法
// 此時,系統自動觸發了魔術方法:__callStatic(),Facade重寫了此方法:
public static function __callStatic($method, $params)
{
return call_user_func_array([static::createFacade(), $method], $params);
}
// 可見,最後呼叫的是使用者自定義函式:call_user_func_array([例項, 方法], 引數),為了獲得Config例項,Facade又定義了一個獲取物件的方法:
/**
* 建立Facade例項
* @static
* @access protected
* @param string $class 類名或標識
* @param array $args 變數
* @param bool $newInstance 是否每次建立新的例項
* @return object
*/
protected static function createFacade($class = '', $args = [], $newInstance = false)
{
$class = $class ?: static::class;
$facadeClass = static::getFacadeClass();
if ($facadeClass) {
$class = $facadeClass;
} elseif (isset(self::$bind[$class])) {
$class = self::$bind[$class];
}
if (static::$alwaysNewInstance) {
$newInstance = true;
}
return Container::getInstance()->make($class, $args, $newInstance);
}
// 其內部是通過容器來例項化物件
// 因為在base.php中已經將 think\Config 類繫結到 config 這個標識
Container::getInstance()->bind([
'config' => Config::class
])
// 在 createFacade 方法中,獲取類的名稱:$class = $class ?: static::class; 即得到 config 這個標識
// 在容器的make方法中,根據config標識,找到繫結的 think\Config 類,並呼叫其動態方法 get。
facade\Config::get('app_debug');
// 最後呼叫的是:
(new think\Config())->get('app_debug');