国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > PHP > 正文

thinkphp5.1框架中容器(Container)和門面(Facade)的實現(xiàn)方法分析

2024-05-05 00:10:45
字體:
供稿:網(wǎng)友

本文實例講述了thinkphp5.1框架中容器(Container)和門面(Facade)的實現(xiàn)方法。分享給大家供大家參考,具體如下:

tp5.1中引入了容器(Container)和門面(Facade)這兩個新的類

官方文檔已經(jīng)給出了定義:

容器(Container)實現(xiàn)類的統(tǒng)一管理,確保對象實例的唯一性。

門面(Facade)為容器(Container)中的類提供了一個靜態(tài)調(diào)用接口,相比于傳統(tǒng)的靜態(tài)方法調(diào)用, 帶來了更好的可測試性和擴展性,你可以為任何的非靜態(tài)類庫定義一個facade類。

深入源碼,我們來看看它到底是如何實現(xiàn)的:

// 在框架目錄下的base.php文件// 注冊核心類到容器Container::getInstance()->bind([  'app'          => App::class,  'build'         => Build::class,  'cache'         => Cache::class,  'config'        => Config::class,  ...]);// 注冊核心類的靜態(tài)代理Facade::bind([  facade/App::class   => App::class,  facade/Build::class  => Build::class,  facade/Cache::class  => Cache::class,  facade/Config::class  => Config::class,  ...]);// 注冊類庫別名Loader::addClassAlias([  'App'   => facade/App::class,  'Build'  => facade/Build::class,  'Cache'  => facade/Cache::class,  'Config'  => facade/Config::class,  ...]);

容器實現(xiàn):

這里,框架已經(jīng)幫我們綁定了系統(tǒng)常用類到容器中,在之后使用時,只需要調(diào)用助手函數(shù) app()進行容器中的類解析調(diào)用,對于已經(jīng)綁定的類標識,會自動快速實例化。

// 實例化緩存類app('cache');// app('cache', ['file']); 參數(shù)化調(diào)用// 相當于執(zhí)行了Container::get('cache');// 查看源碼,Container調(diào)用的其實是make方法,在該方法里調(diào)用反射等實現(xiàn)類的實例化,過程如下:public function make($abstract, $vars = [], $newInstance = false){  if (true === $vars) {    // 總是創(chuàng)建新的實例化對象    $newInstance = true;    $vars    = [];  }  if (isset($this->instances[$abstract]) && !$newInstance) {    $object = $this->instances[$abstract];  } else {    if (isset($this->bind[$abstract])) {      $concrete = $this->bind[$abstract];       // 閉包實現(xiàn)      if ($concrete instanceof /Closure) {        $object = $this->invokeFunction($concrete, $vars);      } else {        $object = $this->make($concrete, $vars, $newInstance);      }    } else {       // 反射實現(xiàn)      $object = $this->invokeClass($abstract, $vars);    }    if (!$newInstance) {      $this->instances[$abstract] = $object;    }  }  return $object;}/** * 調(diào)用反射執(zhí)行類的實例化 支持依賴注入 * @access public * @param string  $class 類名 * @param array   $vars 變量 * @return mixed */public function invokeClass($class, $vars = []){  $reflect   = new /ReflectionClass($class);  $constructor = $reflect->getConstructor();  if ($constructor) {    $args = $this->bindParams($constructor, $vars);  } else {    $args = [];  }  return $reflect->newInstanceArgs($args);}/** * 執(zhí)行函數(shù)或者閉包方法 支持參數(shù)調(diào)用 * @access public * @param string|array|/Closure $function 函數(shù)或者閉包 * @param array         $vars   變量 * @return mixed */public function invokeFunction($function, $vars = []){  $reflect = new /ReflectionFunction($function);  $args  = $this->bindParams($reflect, $vars);  return $reflect->invokeArgs($args);}

簡而言之,容器內(nèi)部是通過反射類或閉包等來實現(xiàn)類的實例化。

門面實現(xiàn):

以一個例子來分析:

facade/Config::get('app_debug');

我們來分析一下它的實現(xiàn)方式:

// thinkphp/library/facade/Config 類namespace think/facade;use think/Facade;class Config extends Facade{}// 從源代碼上看 Config本身沒有任何方法,它繼承了Facade的方法,但Facade并沒有g(shù)et這個靜態(tài)方法// 此時,系統(tǒng)自動觸發(fā)了魔術(shù)方法:__callStatic(),Facade重寫了此方法:public static function __callStatic($method, $params){  return call_user_func_array([static::createFacade(), $method], $params);}// 可見,最后調(diào)用的是用戶自定義函數(shù):call_user_func_array([實例, 方法], 參數(shù)),為了獲得Config實例,F(xiàn)acade又定義了一個獲取對象的方法:/** * 創(chuàng)建Facade實例 * @static * @access protected * @param string  $class     類名或標識 * @param array   $args      變量 * @param bool   $newInstance  是否每次創(chuàng)建新的實例 * @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);}// 其內(nèi)部是通過容器來實例化對象// 因為在base.php中已經(jīng)將 think/Config 類綁定到 config 這個標識Container::getInstance()->bind([  'config' => Config::class])// 在 createFacade 方法中,獲取類的名稱:$class = $class ?: static::class; 即得到 config 這個標識// 在容器的make方法中,根據(jù)config標識,找到綁定的 think/Config 類,并調(diào)用其動態(tài)方法 get。facade/Config::get('app_debug');// 最后調(diào)用的是:(new think/Config())->get('app_debug');

簡而言之,門面的實現(xiàn)是通過PHP的魔術(shù)方法 __callStatic,再配合容器來實現(xiàn)動態(tài)類的靜態(tài)化調(diào)用。

希望本文所述對大家基于ThinkPHP框架的PHP程序設(shè)計有所幫助。


注:相關(guān)教程知識閱讀請移步到PHP教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 卢龙县| 阿合奇县| 青川县| 宣汉县| 通辽市| 云霄县| 乌拉特前旗| 武定县| 龙泉市| 普兰县| 满城县| 色达县| 鄂伦春自治旗| 台北市| 溧阳市| 黄石市| 扬中市| 大同县| 嫩江县| 铁力市| 博乐市| 汉寿县| 深泽县| 德阳市| 镇江市| 达拉特旗| 陆丰市| 稻城县| 盐亭县| 乳源| 五台县| 海兴县| 静乐县| 米脂县| 盘山县| 唐海县| 高邮市| 明光市| 修武县| 兴仁县| 工布江达县|