首页 后端开发 php教程 Laravel中Facade是什么?

Laravel中Facade是什么?

Sep 23, 2017 am 09:12 AM
facade laravel

Facade其实是一个容器中类的静态代理,他可以让你以静态的方式来调用存放在容器中任何对象的任何方法。下面这篇文章主要给大家介绍了关于Laravel中Facade的加载过程与原理的相关资料,需要的朋友可以参考下。

Laravel中Facade是什么?

官方文档给出的定义

“Facades 为应用的 服务容器 提供了一个「静态」 接口。Laravel 自带了很多 Facades,可以访问绝大部分功能。Laravel Facades 实际是服务容器中底层类的 「静态代理」 ,相对于传统静态方法,在使用时能够提供更加灵活、更加易于测试、更加优雅的语法。”

你不必 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(&#39;app.name&#39;);
 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(&#39;foo&#39;, &#39;bar&#39;);

$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(&#39;app.name&#39;);
 }
}
登录后复制

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

<?php

use Illuminate\Support\Facades\Config;

class Test
{
 public function index()
 {
  Config::get(&#39;app.name&#39;);
 }
}
登录后复制

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

<?php

public static function __callStatic($method, $args)
{
 $instance = static::getFacadeRoot();

 if (! $instance) {
  throw new RuntimeException(&#39;A facade root has not been set.&#39;);
 }

 return $instance->$method(...$args);
}
登录后复制

getFacadeRoot 方法用于获取别名类的具体实列,我们知道,所有的 Facade 类都需要定义一个 getFacadeAccessor 方法。该方法可能的返回值有:

  • String 类型的字符串(如 config, db)

  • String 类型的类字符串 (如 App\Service\SomeService)

  • Object 具体的实列化对象

  • Closure 闭包

如 Config Facade 的 getFacadeAccessor 方法如下:

protected static function getFacadeAccessor()
{
 return &#39;config&#39;;
}
登录后复制

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(&#39;config&#39;, $config = new Repository($items));
登录后复制

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

更多相关知识,请访问 PHP中文网!!

以上是Laravel中Facade是什么?的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
威尔R.E.P.O.有交叉游戏吗?
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Laravel - Artisan 命令 Laravel - Artisan 命令 Aug 27, 2024 am 10:51 AM

Laravel - Artisan 命令 - Laravel 5.7 提供了处理和测试新命令的新方法。它包括测试 artisan 命令的新功能,下面提到了演示?

Laravel - Artisan 控制台 Laravel - Artisan 控制台 Aug 27, 2024 am 10:51 AM

Laravel - Artisan Console - Laravel 框架提供了三种主要的命令行交互工具,即:Artisan、Ticker 和 REPL。本章详细介绍了 Artisan。

Laravel - 分页自定义 Laravel - 分页自定义 Aug 27, 2024 am 10:51 AM

Laravel - 分页自定义 - Laravel 包含分页功能,可帮助用户或开发人员包含分页功能。 Laravel 分页器与查询构建器和 Eloquent ORM 集成。自动分页方法

在Laravel中如何获取邮件发送失败时的退信代码? 在Laravel中如何获取邮件发送失败时的退信代码? Apr 01, 2025 pm 02:45 PM

Laravel邮件发送失败时的退信代码获取方法在使用Laravel开发应用时,经常会遇到需要发送验证码的情况。而在实�...

Laravel计划任务不执行:schedule:run命令后任务未运行怎么办? Laravel计划任务不执行:schedule:run命令后任务未运行怎么办? Mar 31, 2025 pm 11:24 PM

Laravel计划任务运行无响应排查在使用Laravel的计划任务调度时,不少开发者会遇到这样的问题:schedule:run...

在 Laravel 中,如何处理邮件发送验证码失败的情况? 在 Laravel 中,如何处理邮件发送验证码失败的情况? Mar 31, 2025 pm 11:48 PM

Laravel邮件发送验证码失败时的处理方法在使用Laravel...

在dcat admin中如何实现点击添加数据的自定义表格功能? 在dcat admin中如何实现点击添加数据的自定义表格功能? Apr 01, 2025 am 07:09 AM

在dcatadmin(laravel-admin)中如何实现自定义点击添加数据的表格功能在使用dcat...

Laravel - 转储服务器 Laravel - 转储服务器 Aug 27, 2024 am 10:51 AM

Laravel - 转储服务器 - Laravel 转储服务器随 Laravel 5.7 版本一起提供。以前的版本不包括任何转储服务器。转储服务器将成为 laravel/laravel Composer 文件中的开发依赖项。

See all articles