Laravel Laravel
  • 前言

    • 发行说明
    • 升级向导
    • 贡献导引
    • API 文档
  • 入门指南

    • 安装
    • 配置
    • 文件夹结构
    • Homestead
    • Valet
    • 部署
  • 架构思想

    • 请求生命周期
    • 服务容器
    • 服务提供者
    • Facades:门面
    • Contracts:契约
  • 基础功能

    • 路由
    • 中间件
    • CSRF 保护
    • 控制器
    • 请求
    • 响应
    • 视图
    • URL 生成
    • Session
    • 表单验证
    • 错误处理
    • 日志
  • 前端开发

    • Blade 模板
    • 本地化
    • 前端脚手架
    • 编译资源
  • 安全

    • 身份认证
    • API 身份认证
    • 授权
    • 邮件验证(new)
    • 加密
    • 哈希
    • 重置密码
  • 深入话题

    • Artisan 命令行
    • 广播
    • 缓存
    • 集合
    • 事件
    • 文件存储
    • 辅助函数
    • Mail
    • 消息通知
    • 扩展包开发
    • 队列
    • 任务调度
  • 数据库

    • 快速入门
    • 查询构造器
    • 分页
    • 数据库迁移
    • 数据填充
    • Redis
  • Eloquent ORM

    • 快速入门
    • 关联关系
    • Eloquent 集合
    • 修改器
    • API 资源
    • 序列化
  • 测试

    • 快速入门
    • HTTP 测试
    • 命令行测试(new)
    • 浏览器测试
    • 数据库测试
    • 测试模拟器Mocking
  • 官方扩展包

    • Cashier
    • Dusk浏览器测试(new)
    • Envoy部署工具
    • Horizon队列管理工具
    • Passport OAuth 认证
    • Scout全文搜索
    • Socialite社会化登录
    • Telescope 调试工具(new)
Icon

提示 您正在浏览旧版本的 Laravel 的文档. 请考虑将你的项目升级到 Laravel 11.x.

9 2

Facades
5.7
8.x 7.x 6.x 5.8 5.7 5.6 5.5 5.4 5.3 5.2 5.1

Laravel 5.7 中文文档 /

未匹配的标注
本文档最新版为 8.x,旧版本可能放弃维护,推荐阅读最新版!

Facades

  • 简介
  • 何时使用 Facades
    • Facades Vs. 依赖注入
    • Facades Vs. 辅助函数
  • Facades 工作原理
  • 实时 Facades
  • Facade 参考类

简介

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

所有的 Laravel Facades 都定义在 Illuminate\Support\Facades 命名空间下。所以,我们可以轻松的使用 Facade :

use Illuminate\Support\Facades\Cache;

Route::get('/cache', function () {
    return Cache::get('key');
});

在 Laravel 文档中,有很多示例代码都会使用 Facades 来演示框架的各种功能

何时使用 Facades

Facades 有很多优点,它提供了简单,易记的语法,从而无需手动注入或配置长长的类名。此外,由于他们对 PHP 静态方法的独特调用,使得测试起来非常容易。

然而,在使用 Facades 时,有些地方需要特别注意。使用 Facades 时最主要的危险就是会引起类作用范围的膨胀。由于 Facades 使用起来非常简单并且不需要注入,就会使得我们不经意间在单个类中使用许多 Facades ,从而导致类变得越来越大。然而使用依赖注入的时候,使用的类越多,构造方法就会越长,在视觉上注意到这个类有些庞大了。因此在使用 Facades 的时候,要特别注意控制类的大小,让类的作用范围保持短小。

{tip} 在开发与 Laravel 进行交互的第三方扩展包时,最好选择注入 Laravel 契约 而不使用 Facades 。因为扩展包是在 Laravel 之外构建,你无法使用 Laravel Facades 测试辅助函数

Facades Vs. 依赖注入

依赖注入的主要优点之一是切换注入类的实现。这在测试的时候很有用,因为你可以注入一个 模拟或 stub ,并断言 stub 上调出各种方法。

通常,真正的静态方法是不可能模拟或 stub 的。但是 Facades 使用动态方法对服务容器中解析出来的对象方法的调用进行了代理,我们也可以像测试注入类实例一样测试 Facades。比如,像下面的路由:

use Illuminate\Support\Facades\Cache;

Route::get('/cache', function () {
    return Cache::get('key');
});

我们可以带上我们期望的参数编写下面的测试代码来验证Cache::get 方法:

use Illuminate\Support\Facades\Cache;

/**
 * 一个基础功能的测试
 *
 * @return void
 */
public function testBasicExample()
{
    Cache::shouldReceive('get')
         ->with('key')
         ->andReturn('value');

    $this->visit('/cache')
         ->see('value');
}

Facades Vs. 辅助函数

除了 Facades,Laravel 还包含各种 『辅助函数』 来实现这些常用功能,比如生成视图、触发事件、任务调度或者发送 HTTP 响应。许多辅助函数都有与之对应的 Facades 。例如,下面这个 Facades 和辅助函数的作用是一样的:

return View::make('profile');

return view('profile');

Facade 和辅助函数之间没有实际的区别。当你使用辅助函数时,你可以像测试相应的 Facade 那样进行测试。例如,下面的路由:

Route::get('/cache', function () {
    return cache('key');
});

在底层实现,辅助函数 cache 实际是调用 Cache 这个 Facade 的 get 方法。因此,尽管我们使用的是辅助函数,我们依然可以带上我们期望的参数编写下面的测试代码来验证Cache::get 方法:

use Illuminate\Support\Facades\Cache;

/**
 * 一个基础功能的测试用例
 *
 * @return void
 */
public function testBasicExample()
{
    Cache::shouldReceive('get')
         ->with('key')
         ->andReturn('value');

    $this->visit('/cache')
         ->see('value');
}

Facades 工作原理

在 Laravel 应用中,Facade 就是一个可以从容器访问对象的类。其中核心的部件就是Facade类。不管是 Laravel 自带的 Facades,还是自定义的 Facades,都继承自Illuminate\Support\Facades\Facade类。

Facade基类使用了__callStatic()魔术方法,直到对象从容器中被解析出来后,才会进行调用。在下面的例子中,调用了 Laravel 的缓存系统。通过浏览这段代码,可以假定在Cache类中调用了静态方法get:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;

class UserController extends Controller
{
    /**
     * 显示给定用户的信息。
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        $user = Cache::get('user:'.$id);

        return view('profile', ['user' => $user]);
    }
}

注意在上面这段代码中,我们『导入』了 Cache Facade。这个 Facade 作为访问Illuminate\Contracts\Cache\Factory接口底层实现的代理。我们使用 Facade 进行的任何调用都将传递给 Laravel 缓存服务的底层实例。

如果我们看一下Illuminate\Support\Facades\Cache这个类,你会发现类中根本没有get这个静态方法:

class Cache extends Facade
{
    /**
     * 获取组件的注册名称。
     *
     * @return string
     */
    protected static function getFacadeAccessor() { return 'cache'; }
}

CacheFacade 继承了Facade类,并且定义了getFacadeAccessor()方法。这个方法的作用是返回服务容器绑定的名称。当用户调用CacheFacade 中的任何静态方法时,Laravel 会从 服务容器 中解析cache绑定以及该对象运行所请求的方法(在这个例子中就是get方法)。

实时 Facades

使用实时 Facades,你可以将应用程序中的任何类视为 Facade。为了说明这是如何使用的,我们来看看另一种方法。例如,假设我们的Podcast模型有一个publish方法。然而,为了发布 Podcast,我们需要注入一个Publisher实例:

<?php

namespace App;

use App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * 发布 Podcast。
     *
     * @param  Publisher  $publisher
     * @return void
     */
    public function publish(Publisher $publisher)
    {
        $this->update(['publishing' => now()]);

        $publisher->publish($this);
    }
}

将发布者的实现注入到该方法中,我们可以轻松地测试这种方法,因为我们可以模拟注入的发布者。但是,它要求我们每次调用publish方法时都要传递一个发布者实例。使用实时的 Facades,我们可以保持同样的可测试性,而不需要显式地通过Publisher实例。要生成实时Facade,请在导入类的名称空间中加上Facades:

<?php

namespace App;

use Facades\App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * 发布 Podcast。
     *
     * @return void
     */
    public function publish()
    {
        $this->update(['publishing' => now()]);

        Publisher::publish($this);
    }
}

当使用实时 Facade 时,发布者实现将通过使用Facades前缀后出现的接口或类名的部分来解决服务容器的问题。在测试时,我们可以使用 Laravel 的内置 facade 测试辅助函数来模拟这种方法调用:

<?php

namespace Tests\Feature;

use App\Podcast;
use Tests\TestCase;
use Facades\App\Contracts\Publisher;
use Illuminate\Foundation\Testing\RefreshDatabase;

class PodcastTest extends TestCase
{
    use RefreshDatabase;

    /**
     * 一个测试演示。
     *
     * @return void
     */
    public function test_podcast_can_be_published()
    {
        $podcast = factory(Podcast::class)->create();

        Publisher::shouldReceive('publish')->once()->with($podcast);

        $podcast->publish();
    }
}

Facade 类参考

在下面你可以找到每个 Facade 类及其对应的底层类。这是一个查找给定 Facade 类 API 文档的工具。服务容器绑定 的关键信息也包含在内。

Facade Class Service Container Binding
App Illuminate\Foundation\Application app
Artisan Illuminate\Contracts\Console\Kernel artisan
Auth Illuminate\Auth\AuthManager auth
Auth (Instance) Illuminate\Contracts\Auth\Guard auth.driver
Blade Illuminate\View\Compilers\BladeCompiler blade.compiler
Broadcast Illuminate\Contracts\Broadcasting\Factory  
Broadcast (Instance) Illuminate\Contracts\Broadcasting\Broadcas...  
Bus Illuminate\Contracts\Bus\Dispatcher  
Cache Illuminate\Cache\CacheManager cache
Cache (Instance) Illuminate\Cache\Repository cache.store
Config Illuminate\Config\Repository config
Cookie Illuminate\Cookie\CookieJar cookie
Crypt Illuminate\Encryption\Encrypter encrypter
DB Illuminate\Database\DatabaseManager db
DB (Instance) Illuminate\Database\Connection db.connection
Event Illuminate\Events\Dispatcher events
File Illuminate\Filesystem\Filesystem files
Gate Illuminate\Contracts\Auth\Access\Gate  
Hash Illuminate\Contracts\Hashing\Hasher hash
Lang Illuminate\Translation\Translator translator
Log Illuminate\Log\Logger log
Mail Illuminate\Mail\Mailer mailer
Notification Illuminate\Notifications\ChannelManager  
Password Illuminate\Auth\Passwords\PasswordBrokerMa... auth.password
Password (Instance) Illuminate\Auth\Passwords\PasswordBroker auth.password.broker
Queue Illuminate\Queue\QueueManager queue
Queue (Instance) Illuminate\Contracts\Queue\Queue queue.connection
Queue (Base Class) Illuminate\Queue\Queue  
Redirect Illuminate\Routing\Redirector redirect
Redis Illuminate\Redis\RedisManager redis
Redis (Instance) Illuminate\Redis\Connections\Connection redis.connection
Request Illuminate\Http\Request request
Response Illuminate\Contracts\Routing\ResponseFacto...  
Response (Instance) Illuminate\Http\Response  
Route Illuminate\Routing\Router router
Schema Illuminate\Database\Schema\Builder  
Session Illuminate\Session\SessionManager session
Session (Instance) Illuminate\Session\Store session.store
Storage Illuminate\Filesystem\FilesystemManager filesystem
Storage (Instance) Illuminate\Contracts\Filesystem\Filesystem filesystem.disk
URL Illuminate\Routing\UrlGenerator url
Validator Illuminate\Validation\Factory validator
Validator (Instance) Illuminate\Validation\Validator  
View Illuminate\View\Factory view
View (Instance) Illuminate\View\View  

本文章首发在 网站上。


上一篇 下一篇

成为Laravel合作伙伴

Laravel Partners是提供一流Laravel开发和咨询服务的精英商店。我们每个合作伙伴都可以帮助您制定一个精美,结构完善的项目.

我们的伙伴
Laravel
亮点
  • Our Team
  • 发布说明
  • 入门
  • 路由
  • Blade 模板
  • 身份验证
  • 用户授权
  • Artisan 控制台
  • 数据库
  • Eloquent ORM
  • 测试
资源
  • Laravel Bootcamp
  • Laracasts
  • Laravel News
  • Laracon
  • Laracon EU
  • Laracon India
  • Jobs
  • Forums
  • Trademark
  • 版本发布时间
  • 包开发
  • 命令行应用
  • TALL stack全栈开发
  • Blade UI Kit
  • 前端资源构建
伙伴
  • WebReinvent
  • Vehikl
  • Tighten
  • 64 Robots
  • Active Logic
  • Byte 5
  • Curotec
  • Cyber-Duck
  • DevSquad
  • Jump24
  • Kirschbaum
生态系统
  • Cashier
  • Dusk
  • Echo
  • Envoyer
  • Forge
  • Horizon
  • Nova
  • Octane
  • Sail
  • Sanctum
  • Scout
  • Spark
  • Telescope
  • Valet
  • Vapor

Laravel是一个具有表达力,优雅语法的Web应用程序框架。我们认为,发展必须是一种令人愉悦的创造力,才能真正实现。Laravel试图通过减轻大多数Web项目中使用的常见任务来减轻开发的痛苦.

Laravel是Taylor Otwell的商标.
Copyright © 2011-2025 Laravel中文网 LLC.

  • Twitter
  • GitHub
  • Discord
Laravel 全栈开发网 推荐使用阿里云 按Ctrl+D试试