日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Laravel Facade的加载过程及原理

發(fā)布時間:2023/12/29 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Laravel Facade的加载过程及原理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Facades(讀音:/f??s?d/ )為應(yīng)用程序的?服務(wù)容器?中可用的類提供了一個「靜態(tài)」接口。你不必?use?一大串的命名空間,也不用實例化對象,就能訪問對象的具體方法。

use Config;class Test {public function index(){return Config::get('app.name');} }

Facade 的啟動與注冊

Facade 的啟動引導(dǎo)是在?Illuminate\Foundation\Bootstrap\RegisterFacades?中注冊的。

public function bootstrap(Application $app) {Facade::clearResolvedInstances();Facade::setFacadeApplication($app);AliasLoader::getInstance(array_merge($app->make('config')->get('app.aliases', []),$app->make(PackageManifest::class)->aliases()))->register(); }

默認的別名配置是從?app?配置文件下的?aliases?讀取的,PackageManifest?是?laravel 5.5?新增的?包自動發(fā)現(xiàn)規(guī)則,這里我們暫時不考慮?PackageManifest?包提供的別名。

其中,array_merge?返回如下格式的數(shù)組:

"App" => "Illuminate\Support\Facades\App""Artisan" => "Illuminate\Support\Facades\Artisan""Auth" => "Illuminate\Support\Facades\Auth""Blade" => "Illuminate\Support\Facades\Blade"...

上面代碼將通過?AliasLoader?把所有的?facade?注冊進自動加載。其核心就是?php?的?spl_autoload_register。

/*** Prepend the load method to the auto-loader stack.** @return void*/protected function register(){if (! $this->registered) {spl_autoload_register([$this, 'load'], true, true);$this->registered = true;}}

注冊完成后,后續(xù)所有?use?的類都將通過?load?函數(shù)來完成類的自動加載。

注意,這里在定義?spl_autoload_register?時,最后面的參數(shù)傳的是?true。當該參數(shù)是?true?時,spl_autoload_register()?會添加函數(shù)到隊列之首,而不是隊列尾部。(優(yōu)先通過該函數(shù)來完成自動加載)

也就是說,

<?phpuse Config; use App\User;class Test {public function index(){Config::get('app.name');new User();} }

不管我們?use?的是具體存在的類(App\User)還是別名?(Config),都將最先通過?load?函數(shù)來完成自動加載,當該函數(shù)返回?false?時,再由其他自動加載函數(shù)來完成自動加載(如?composer psr-4)。

在?AliasLoader?的?load?方法中,主要是用了?class_alias?函數(shù)來實現(xiàn)的別名自動加載。

public function load($alias) {if (isset($this->aliases[$alias])) {return class_alias($this->aliases[$alias], $alias);} }

關(guān)于?class_alias?這里帖一個官方的列子:

class foo { }class_alias('foo', 'bar');$a = new foo; $b = new bar;// the objects are the same var_dump($a == $b, $a === $b); //true var_dump($a instanceof $b); //false// the classes are the same var_dump($a instanceof foo); //true var_dump($a instanceof bar); //truevar_dump($b instanceof foo); //true var_dump($b instanceof bar); //true

Facade 的加載

當我們在使用?Facade?時,如:

<?phpuse Config;class Test {public function index(){Config::get('app.name');} }

實際上加載的是?Illuminate\Support\Facades\Config?類(因為我們已經(jīng)注冊了?class_alias),相當于:

<?phpuse Illuminate\Support\Facades\Config;class Test {public function index(){Config::get('app.name');} }

而所有的?Facade?都繼承自?Illuminate\Support\Facades\Facade?類,在該基類中定義了一個?__callStatic?方法,已至于我們能夠輕松地使用?Facade(不用實列化)。

<?phppublic static function __callStatic($method, $args) {$instance = static::getFacadeRoot();if (! $instance) {throw new RuntimeException('A facade root has not been set.');}return $instance->$method(...$args); }

getFacadeRoot?方法用于獲取別名類的具體實列,我們知道,所有的?Facade?類都需要定義一個?getFacadeAccessor?方法。該方法可能的返回值有:

  • String 類型的字符串(如?config,?db)
  • String 類型的類字符串 (如?App\Service\SomeService)
  • Object 具體的實列化對象
  • Closure 閉包
  • 如?Config Facade?的?getFacadeAccessor?方法如下:

    protected static function getFacadeAccessor() {return 'config'; }

    getFacadeRoot?方法將根據(jù)?getFacadeAccessor()?的返回值,從容器從取出對應(yīng)的實列對象。

    public static function getFacadeRoot() {$name = static::getFacadeAccessor();if (is_object($name)) {return $name;}if (isset(static::$resolvedInstance[$name])) {return static::$resolvedInstance[$name];}return static::$resolvedInstance[$name] = static::$app[$name]; }

    由于 APP 容器中已經(jīng)注冊過?config?的實列

    <?php //Illuminate\Foundation\Bootstrap/LoadConfiguration$app->instance('config', $config = new Repository($items));

    所以?\Config::get('app.name', 'dafault)?實際訪問的是?Repository?實列的?get('app.name', 'default')?方法。

    參考文獻:

    https://segmentfault.com/a/1190000011274118

    總結(jié)

    以上是生活随笔為你收集整理的Laravel Facade的加载过程及原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。