Facades 类别名设置流程 (class_alias)
Facade类别名设置
场景描述:
// web.php中
Route::get('/', function () {
return view('welcome');
});
- 为何能直接使用Route,其实是调用了Illuminate\Support\Facades\Route类。然后通过facade获取对象执行对象方法(看我上一篇文章facade原理)
- 为何调用Route也就调用了Illuminate\Support\Facades\Route类,这就是这篇文章的核心:
- class_alias:为一个类创建别名
核心代码 类:Illuminate\Foundation\AliasLoader
public function load($alias)
{
if (static::$facadeNamespace && strpos($alias, static::$facadeNamespace) === 0) {
$this->loadFacade($alias);
return true;
}
// $alias来自于config/app.php中aliases数组中的一个键值队如:
// 'Route' => Illuminate\Support\Facades\Route::class 中的键“Route”
if (isset($this->aliases[$alias])) {
//'Route' => Illuminate\Support\Facades\Route::class,
// class_alias:为一个类创建别名
return class_alias($this->aliases[$alias], $alias);
}
}
具体流程如下:
- 入口文件index.php
// 此处才包含了设置facade类别名的操作 $response = $kernel->handle( $request = Illuminate\Http\Request::capture() );
-
进入Illuminate\Foundation\Http\Kernel类(Kernel.php)
/** * Handle an incoming HTTP request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function handle($request) { try { $request->enableHttpMethodParameterOverride(); // 进入这行 $response = $this->sendRequestThroughRouter($request); } catch (Exception $e) { $this->reportException($e); $response = $this->renderException($request, $e); } catch (Throwable $e) { $this->reportException($e = new FatalThrowableError($e)); $response = $this->renderException($request, $e); } $this->app['events']->dispatch( new Events\RequestHandled($request, $response) ); return $response; }
-
进入方法sendRequestThroughRouter
protected function sendRequestThroughRouter($request) { // 将request对象绑定到容器$app的instances数组里面,实现单例模式 $this->app->instance('request', $request); // 实际执行了这行 unset(static::$resolvedInstance["request"]); Facade::clearResolvedInstance('request'); // 重点:这里的操作包含执行了Facade类的别名设置 $this->bootstrap(); return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter()); }
- 进入bootstrap方法
public function bootstrap() { if (! $this->app->hasBeenBootstrapped()) { // 执行容器实例$app里面的bootstrapWith,携带参数是$this->bootstrappers() // $this->bootstrappers()最终返回的数组是Kernel实例的属性$bootstrappers // protected $bootstrappers = [ // \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, // \Illuminate\Foundation\Bootstrap\LoadConfiguration::class, // \Illuminate\Foundation\Bootstrap\HandleExceptions::class, // \Illuminate\Foundation\Bootstrap\RegisterFacades::class, // \Illuminate\Foundation\Bootstrap\RegisterProviders::class, // \Illuminate\Foundation\Bootstrap\BootProviders::class, // ]; $this->app->bootstrapWith($this->bootstrappers()); } }
-
进入Illuminate\Foundation\Application类的bootstrapWith方法
public function bootstrapWith(array $bootstrappers) { $this->hasBeenBootstrapped = true; foreach ($bootstrappers as $bootstrapper) { $this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]); // 当循环到\Illuminate\Foundation\Bootstrap\RegisterFacades::class // Illuminate\Foundation\Bootstrap\RegisterFacades解析出类的RegisterFacades的实例对象 // 调用RegisterFacades的bootstrap方法 $this->make($bootstrapper)->bootstrap($this); $this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]); } }
-
进入Illuminate\Foundation\Bootstrap\RegisterFacades类,进入bootstrap方法
/** * Bootstrap the given application. * * @param \Illuminate\Contracts\Foundation\Application $app * @return void */ public function bootstrap(Application $app) { Facade::clearResolvedInstances(); Facade::setFacadeApplication($app); // 这里就是上面所说的 核心代码 // 将config/app.php 里的aliases数组里面的Facades类设置别名 AliasLoader::getInstance(array_merge( $app->make('config')->get('app.aliases', []), $app->make(PackageManifest::class)->aliases() ))->register(); }
- 进入Illuminate\Foundation\AliasLoader类,执行文章开头说得核心代码
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: