全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

Laravel中Facade的加载过程与原理详解

前言

本文主要给大家介绍了关于Laravel中Facade加载过程与原理的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

简介

Facades(读音:/fəˈsäd/ )为应用程序的 服务容器 中可用的类提供了一个「静态」接口。你不必 use 一大串的命名空间,也不用实例化对象,就能访问对象的具体方法。

use Config;

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

Facade 的启动与注册

Facade 的启动引导是在 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 新增的 包自动发现 规则,这里我们暂时不考虑 PackageManifest 包提供的别名。

其中,array_merge 返回如下格式的数组:

 "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;
 }
 }

注册完成后,后续所有 use 的类都将通过 load 函数来完成类的自动加载。

注意:这里在定义 spl_autoload_register 时,最后面的参数传的是 true。当该参数是 true 时,spl_autoload_register() 会添加函数到队列之首,而不是队列尾部。(优先通过该函数来完成自动加载)

也就是说,

<?php

use Config;
use App\User;

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

不管我们 use 的是具体存在的类(App\User)还是别名 (Config),都将最先通过 load 函数来完成自动加载,当该函数返回 false 时,再由其他自动加载函数来完成自动加载(如 composer psr-4)。

在 AliasLoader 的 load 方法中,主要是用了 class_alias 函数来实现的别名自动加载。

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

关于 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); //true

var_dump($b instanceof foo); //true
var_dump($b instanceof bar); //true

Facade 的加载

当我们在使用 Facade 时,如:

<?php

use Config;

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

实际上加载的是 Illuminate\Support\Facades\Config 类(因为我们已经注册了 class_alias),相当于:

<?php

use Illuminate\Support\Facades\Config;

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

而所有的 Facade 都继承自 Illuminate\Support\Facades\Facade 类,在该基类中定义了一个 __callStatic 方法,已至于我们能够轻松地使用 Facade(不用实列化)。

<?php

public 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 方法将根据 getFacadeAccessor() 的返回值,从容器从取出对应的实列对象。

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 容器中已经注册过 config 的实列

<?php
//Illuminate\Foundation\Bootstrap/LoadConfiguration

$app->instance('config', $config = new Repository($items));

所以 \Config::get('app.name', 'dafault) 实际访问的是 Repository 实列的 get('app.name', 'default') 方法。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。


# laravel  # facade  # 原理  # 设置  # 跟我学Laravel之请求(Request)的生命周期  # Laravel 5框架学习之模型、控制器、视图基础流程  # 跟我学Laravel之请求与输入  # Laravel 5.5中为响应请求提供的可响应接口详解  # Laravel 5.4重新登录实现跳转到登录前页面的原理和方法  # Laravel中间件实现原理详解  # 浅谈Laravel队列实现原理解决问题记录  # Laravel模型事件的实现原理详解  # Laravel框架生命周期与原理分析  # 的是  # 自动加载  # 来完成  # 加载  # 都将  # 列子  # 返回值  # 是在  # 相关内容  # 就能  # 说了  # 不多  # 是从  # 一大  # 用了  # 给大家  # 当我们  # 这篇文章  # 谢谢大家  # 来实现 


相关文章: 合肥制作网站的公司有哪些,合肥聚美网络科技有限公司介绍?  非常酷的网站设计制作软件,酷培ai教育官方网站?  电商网站制作公司有哪些,1688网是什么意思?  东莞专业网站制作公司有哪些,东莞招聘网站哪个好?  建站主机如何选?高性价比方案全解析  如何快速建站并高效导出源代码?  网站制作与设计教程,如何制作一个企业网站,建设网站的基本步骤有哪些?  一键制作网站软件下载安装,一键自动采集网页文档制作步骤?  学校为何禁止电信移动建设网站?  如何在IIS7上新建站点并设置安全权限?  如何高效完成自助建站业务培训?  南京做网站制作公司,南京哈发网络有限公司,公司怎么样,做网页美工DIV+CSS待遇怎么样?  盐城做公司网站,江苏电子版退休证办理流程?  如何选购建站域名与空间?自助平台全解析  香港服务器如何优化才能显著提升网站加载速度?  logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?  临沂网站制作企业,临沂第三中学官方网站?  制作假网页,招聘网的薪资待遇,会有靠谱的吗?一面试又各种折扣?  定制建站方案优化指南:企业官网开发与建站费用解析  网站制作知乎推荐,想做自己的网站用什么工具比较好?  如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南  建站之星与建站宝盒如何选择最佳方案?  如何通过VPS建站无需域名直接访问?  宠物网站制作html代码,有没有专门介绍宠物如何养的网站啊?  建站主机无法访问?如何排查域名与服务器问题  官网自助建站系统:SEO优化+多语言支持,快速搭建专业网站  建站主机核心功能解析:服务器选择与网站搭建流程指南  个人网站制作流程图片大全,个人网站如何注销?  实例解析angularjs的filter过滤器  网站制作哪家好,cc、.co、.cm哪个域名更适合做网站?  威客平台建站流程解析:高效搭建教程与设计优化方案  建站为何优先选择香港服务器?  宝塔Windows建站如何避免显示默认IIS页面?  Python lxml的etree和ElementTree有什么区别  如何在Windows环境下新建FTP站点并设置权限?  如何在Golang中处理模块冲突_解决依赖版本不兼容问题  如何在橙子建站上传落地页?操作指南详解  php条件判断怎么写_ifelse和switchcase的使用区别【对比】  百度网页制作网站有哪些,谁能告诉我百度网站是怎么联系?  如何通过西部数码建站助手快速创建专业网站?  详解jQuery中基本的动画方法  早安海报制作网站推荐大全,企业早安海报怎么每天更换?  如何通过免费商城建站系统源码自定义网站主题与功能?  香港服务器部署网站为何提示未备案?  内部网站制作流程,如何建立公司内部网站?  Bpmn 2.0的XML文件怎么画流程图  如何通过.red域名打造高辨识度品牌网站?  ,怎么在广州志愿者网站注册?  免费网站制作appp,免费制作app哪个平台好?  公司网站建设制作费用,想建设一个属于自己的企业网站,该如何去做? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。