注册门面
简介
这一章,我们说一下 Laravel 引导程序之门面的注册,其实质是:执行 Illuminate\Foundation\Bootstrap\RegisterFacades
类中的 bootstrap
方法。
bootstrap
方法
不废话,直接贴 RegisterFacades
类的 bootstrap
方法
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();
}
-
首先,这段代码:
Facade::clearResolvedInstances();
指,清理所有门面公共父类
Illuminate\Support\Facades\Facade
保存的实例缓存。其本质,我们看这段代码
public static function clearResolvedInstances() { static::$resolvedInstance = []; }
明白了吧,就是将静态属性
$resolvedInstance
赋值为空数组,即为清空实例缓存 -
其次,这段代码:
Facade::setFacadeApplication($app);
,门面注册的核心呀。。。我记得刚刚接触 Laravel 的时候,想使用 Redis,官方文档说,用
Illuminate\Support\Facades\Redis
类。我打开Illuminate\Support\Facades\Redis
,一直追踪到其父类,最后卡在下面这个方法上protected static function resolveFacadeInstance($name) { if (is_object($name)) { return $name; } if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } return static::$resolvedInstance[$name] = static::$app[$name]; }
最后一行,有个
static::$app[$name]
,当时就是不知道static::$app
怎么给的值,现在终于找到了。。。我们看一下这行代码
Facade::setFacadeApplication($app);
干了什么吧public static function setFacadeApplication($app) { static::$app = $app; }
看到了吧,
static::$app
就是在这里赋的值。 -
最后,有个小难点,也算是核心吧,就是注册类的别名
AliasLoader::getInstance(array_merge( $app->make('config')->get('app.aliases', []), $app->make(PackageManifest::class)->aliases() ))->register();
这个就是调用
AliasLoader
类的静态方法getInstance
,以$app->make('config')->get('app.aliases', [])
和$app->make(PackageManifest::class)->aliases()
合并后的数组为参数,取返回值,这个返回值是对象,再调用这个对象的register
方法。关于参数,
$app->make('config')->get('app.aliases', [])
是有用的,取得就是app.php
配置文件中的aliases
数组;$app->make(PackageManifest::class)->aliases()
返回的空数组,不用理会1、我们看一下
AliasLoader
类的getInstance
方法public static function getInstance(array $aliases = []) { if (is_null(static::$instance)) { return static::$instance = new static($aliases); } $aliases = array_merge(static::$instance->getAliases(), $aliases); static::$instance->setAliases($aliases); return static::$instance; }
再来张截图,我们看一下参数
$aliases
长什么样?- 首先,是单例模式的经典判断,如果
static::$instance
是null
则实例化自身,否则跳过
实例化自身,要调用 构造函数的,我们看看构造函数
private function __construct($aliases) { $this->aliases = $aliases; }
简单,就是一个
$aliases
数组的赋值- 其次,由于第一次执行,
static::$instance
一定为null
,所以,直接return
自身实例对象
2、我们看一下
AliasLoader
类对象的register
方法public function register() { if (! $this->registered) { $this->prependToLoaderStack(); $this->registered = true; } }
- 首先,判断是否注册过,由于第一次执行,所以未注册过,执行 if 里面的代码
- 其次,我们来看一下
$this->prependToLoaderStack();
干了什么吧
protected function prependToLoaderStack() { spl_autoload_register([$this, 'load'], true, true); }
看到没,类的自动加载方法又新增一个成员,他是
AliasLoader
类对象的load
方法。并优先执行,所以以后自动加载类,会先执行这里的load
方法,然后执行 Composer 注册的自动加载方法也就是说,以后 Laravel 容器
make
一个Redis
会先加载Illuminate\Support\Facades\Redis::class
类,不信,你看 app.php 配置文件 aliases 数组中键为Redis
的值是什么吧。因此说,我们在使用
Illuminate\Support\Facades\Redis
Redis 门面的时候可以简化 use ,如下<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Redis; // 这里就是简化 class UserController extends Controller { /** * 显示给定用户的配置文件。 * * @param int $id * @return Response */ public function showProfile($id) { $user = Redis::get('user:profile:'.$id); return view('user.profile', ['user' => $user]); } }
- 首先,是单例模式的经典判断,如果
本篇如有错误、不当或者需补充的内容,请各位同僚多提宝贵意见。