上次说了provider,那么这次来说说facade
首先是启动的源头,从laravel的kernel类中的$bootstrappers 数组,我们可以看到它的一些系统引导方法,其中的RegisterFacades便是用来注册facade门面类的了。
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, ];
同样是有一个register类,通过这个类进行别名等注册操作
namespace Illuminate\Foundation\Bootstrap; use Illuminate\Foundation\AliasLoader; use Illuminate\Support\Facades\Facade; use Illuminate\Foundation\PackageManifest; use Illuminate\Contracts\Foundation\Application; class RegisterFacades { /** * Bootstrap the given application. * * @param \Illuminate\Contracts\Foundation\Application $app * @return void */ public function bootstrap(Application $app) { //清除facade所有已绑定实例 Facade::clearResolvedInstances(); //将app存入对象 Facade::setFacadeApplication($app); //将这些别名数组通过构造函数存入对象中 AliasLoader::getInstance(array_merge( //通过Illuminate\Config\Repository获取config/app.php中的aliases数组 $app->make('config')->get('app.aliases', []), //还记得最开始的博文中提到的那个包清单吗,这里也从中获取了它的aliases $app->make(PackageManifest::class)->aliases() //通过spl_autoload_register函数注册另一种自动加载函数 ))->register(); } }
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; } private function __construct($aliases) { $this->aliases = $aliases; }
public function register() { if (! $this->registered) { $this->prependToLoaderStack(); $this->registered = true; } } /** * Prepend the load method to the auto-loader stack. * * @return void */ protected function prependToLoaderStack() { //最后通过自动加载函数将本对象中的load方法放入自动加载队列的前端,在我们通过类名调用方法时,会触发自动加载函数队列,会优先触发这个函数,查找到对应文件的路径然后加载相应文件 spl_autoload_register([$this, 'load'], true, true); }
public function load($alias) { //若传入的命名空间不为当前facade数组内才会通过这个方法加载 if (static::$facadeNamespace && strpos($alias, static::$facadeNamespace) === 0) { $this->loadFacade($alias); return true; } //否则直接返回其别名 if (isset($this->aliases[$alias])) { return class_alias($this->aliases[$alias], $alias); } } /** * Load a real-time facade for the given alias. * * @param string $alias * @return void */ protected function loadFacade($alias) { require $this->ensureFacadeExists($alias); } /** * Ensure that the given alias has an existing real-time facade class. * * @param string $alias * @return string */ protected function ensureFacadeExists($alias) { //从缓存中返回路径 if (file_exists($path = storage_path('framework/cache/facade-'.sha1($alias).'.php'))) { return $path; } file_put_contents($path, $this->formatFacadeSt