# Facades
- [簡介](#introduction)
- [何時使用 Facades](#when-to-use-facades)
- [Facades Vs. 依賴注入](#facades-vs-dependency-injection)
- [Facades Vs. 輔助函數](#facades-vs-helper-functions)
- [Facades 工作原理](#how-facades-work)
- [Facade 類參考](#facade-class-reference)
<a name="introduction"></a>
## 簡介
Facades /f??s?d/ 為應用程序的[服務容器](/docs/{{version}}/container)中可用的類提供了一個「靜態」接口。Laravel 自帶了許多的 facades,可以用來訪問其幾乎所有的服務。Laravel facades 就是服務容器里那些基類的「靜態代理」,相比于傳統的靜態方法調用,facades 在提供更簡潔且豐富的語法的同時,還有更好的可測試性和擴展性。
所有的 Laravel facades 都在 `Illuminate\Support\Facades` 這個命名空間下。所以我們可以用類似下面的代碼輕松調用:
use Illuminate\Support\Facades\Cache;
Route::get('/cache', function () {
return Cache::get('key');
});
在 Laravel 的文檔中,很多代碼示例都使用了 facades 來演示框架的各種特性。
<a name="when-to-use-facades"></a>
## 何時使用 Facades
Facades 有很多的好處,它們提供了簡單易記的語法讓你使用 Laravel 的各種功能,你再也不需要記住長長的類名來實現注入或者手動去配置。還有,因為它們對于PHP動態方法的獨特用法,測試起來就非常容易。
但是,在使用 facades 時,有些地方還是需要特別注意。使用 facades 最主要的風險就是會引起類的體積的膨脹。由于 facades 使用起來非常簡單而且不需要注入,我們會不經意間在單個類中大量使用。不像是使用依賴注入,用得越多,構造方法會越長,在視覺上就會引起注意,提醒你這個類有點太龐大了。所以,在使用 facades 時,要特別注意把類的體積控制在一個合理的范圍。
> {tip} 在開發第三方擴展包時,如果需要使用和 Laravel 交互的擴展包,最好是注入 [Laravel contracts](/docs/{{version}}/contracts) 而不是使用 facades,因為擴展包不是在 Laravel 內部使用的,無法使用 Laravel 的 facades 的測試輔助函數。
<a name="facades-vs-dependency-injection"></a>
### Facades Vs. 依賴注入
依賴注入一個主要的好處就是可以切換注入的類的具體實現。這在測試時很有用,因為你可以注入一個 mock 或者 stub 方法并且斷言一些方法在 stub 中被調用。
在以前,靜態方法是不可能被 mock 或者 stub 的。但是因為 facades 調用的是對象的動態方法,我可以像測試注入類的實例一樣測試 facades。舉個例子,有這樣的一個路由:
use Illuminate\Support\Facades\Cache;
Route::get('/cache', function () {
return Cache::get('key');
});
我們可以用下面的測試代碼去驗證 `Cache::get` 方法是否像我們預期那樣被調用并傳入參數。
use Illuminate\Support\Facades\Cache;
/**
* A basic functional test example.
*
* @return void
*/
public function testBasicExample()
{
Cache::shouldReceive('get')
->with('key')
->andReturn('value');
$this->visit('/cache')
->see('value');
}
<a name="facades-vs-helper-functions"></a>
### Facades Vs. 輔助函數
除了 facades,Laravel 還引入了一些「輔助函數」來實現一些常用的功能,比如生成視圖,觸發事件,調度任務或者發送 HTTP 響應。許多輔助函數的功能其實和對應的 facades 一樣。舉例來說,這個 facede 和輔助函數是一樣的:
return View::make('profile');
return view('profile');
Facade 和輔助函數其實沒有本質區別,當使用輔助函數時,你依然可以像使用對應的 facade 一樣測試它們。比如,下面的路由:
Route::get('/cache', function () {
return cache('key');
});
在底層,輔助函數 `cache` 會調用 `Cache` facade 的基類的 `get` 方法。因此,即使我們是在使用輔助函數,我們依然可以用下面的代碼來測試方法是不是被正確的調用了:
use Illuminate\Support\Facades\Cache;
/**
* A basic functional test example.
*
* @return void
*/
public function testBasicExample()
{
Cache::shouldReceive('get')
->with('key')
->andReturn('value');
$this->visit('/cache')
->see('value');
}
<a name="how-facades-work"></a>
## Facades 工作原理
在 Laravel 應用中,一個 facade 其實就是一個提供訪問容器中對象功能的類。其中最核心的部件就是 `Facade` 類。不管是 Laravel 自帶的,還是用戶自定義的 Facades,都是繼承了 `Illuminate\Support\Facades\Facade` 這個類。
`Facade` 類利用了 `__callStatic()` 這個魔術方法來延遲調用容器中的對象的方法。在下面的例子里,調用了 Laravel 緩存系統。在代碼里,我們可能以為 `Cache` 這個類的靜態方法 `get` 被調用了:
<?php
namespace App\Http\Controllers;
use Cache;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Show the profile for the given user.
*
* @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
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor() { return 'cache'; }
}
其實,`Cache` facade 是繼承了基類 `Facade` 并且定義了 `getFacadeAccessor()` 方法。這個方法的功能是返回服務容器中綁定的名字。當用戶調用 `Cache` facade 的靜態方法時,Laravel 會解析到 `cache` 在服務容積里綁定的具體的那個實例對象,并且調用這個對象的相應方法(在這個例子里就是 `get` 方法)。
<a name="facade-class-reference"></a>
## Facade 類參考
在下方你可以找到每個 facade 及其底層的類。這個工具對于通過指定 facade 的來源快速尋找 API 文檔相當有用。可應用的[服務容器綁定](/docs/{{version}}/container)關鍵字也包含在里面。
Facade | Class | Service Container Binding
------------- | ------------- | -------------
App | [Illuminate\Foundation\Application](http://laravel.com/api/{{version}}/Illuminate/Foundation/Application.html) | `app`
Artisan | [Illuminate\Contracts\Console\Kernel](http://laravel.com/api/{{version}}/Illuminate/Contracts/Console/Kernel.html) | `artisan`
Auth | [Illuminate\Auth\AuthManager](http://laravel.com/api/{{version}}/Illuminate/Auth/AuthManager.html) | `auth`
Blade | [Illuminate\View\Compilers\BladeCompiler](http://laravel.com/api/{{version}}/Illuminate/View/Compilers/BladeCompiler.html) | `blade.compiler`
Bus | [Illuminate\Contracts\Bus\Dispatcher](http://laravel.com/api/{{version}}/Illuminate/Contracts/Bus/Dispatcher.html) |
Cache | [Illuminate\Cache\Repository](http://laravel.com/api/{{version}}/Illuminate/Cache/Repository.html) | `cache`
Config | [Illuminate\Config\Repository](http://laravel.com/api/{{version}}/Illuminate/Config/Repository.html) | `config`
Cookie | [Illuminate\Cookie\CookieJar](http://laravel.com/api/{{version}}/Illuminate/Cookie/CookieJar.html) | `cookie`
Crypt | [Illuminate\Encryption\Encrypter](http://laravel.com/api/{{version}}/Illuminate/Encryption/Encrypter.html) | `encrypter`
DB | [Illuminate\Database\DatabaseManager](http://laravel.com/api/{{version}}/Illuminate/Database/DatabaseManager.html) | `db`
DB (Instance) | [Illuminate\Database\Connection](http://laravel.com/api/{{version}}/Illuminate/Database/Connection.html) |
Event | [Illuminate\Events\Dispatcher](http://laravel.com/api/{{version}}/Illuminate/Events/Dispatcher.html) | `events`
File | [Illuminate\Filesystem\Filesystem](http://laravel.com/api/{{version}}/Illuminate/Filesystem/Filesystem.html) | `files`
Gate | [Illuminate\Contracts\Auth\Access\Gate](http://laravel.com/api/5.1/Illuminate/Contracts/Auth/Access/Gate.html) |
Hash | [Illuminate\Contracts\Hashing\Hasher](http://laravel.com/api/{{version}}/Illuminate/Contracts/Hashing/Hasher.html) | `hash`
Lang | [Illuminate\Translation\Translator](http://laravel.com/api/{{version}}/Illuminate/Translation/Translator.html) | `translator`
Log | [Illuminate\Log\Writer](http://laravel.com/api/{{version}}/Illuminate/Log/Writer.html) | `log`
Mail | [Illuminate\Mail\Mailer](http://laravel.com/api/{{version}}/Illuminate/Mail/Mailer.html) | `mailer`
Password | [Illuminate\Auth\Passwords\PasswordBroker](http://laravel.com/api/{{version}}/Illuminate/Auth/Passwords/PasswordBroker.html) | `auth.password`
Queue | [Illuminate\Queue\QueueManager](http://laravel.com/api/{{version}}/Illuminate/Queue/QueueManager.html) | `queue`
Queue (Instance) | [Illuminate\Contracts\Queue\Queue](http://laravel.com/api/{{version}}/Illuminate/Contracts/Queue/Queue.html) | `queue`
Queue (Base Class) | [Illuminate\Queue\Queue](http://laravel.com/api/{{version}}/Illuminate/Queue/Queue.html) |
Redirect | [Illuminate\Routing\Redirector](http://laravel.com/api/{{version}}/Illuminate/Routing/Redirector.html) | `redirect`
Redis | [Illuminate\Redis\Database](http://laravel.com/api/{{version}}/Illuminate/Redis/Database.html) | `redis`
Request | [Illuminate\Http\Request](http://laravel.com/api/{{version}}/Illuminate/Http/Request.html) | `request`
Response | [Illuminate\Contracts\Routing\ResponseFactory](http://laravel.com/api/{{version}}/Illuminate/Contracts/Routing/ResponseFactory.html) |
Route | [Illuminate\Routing\Router](http://laravel.com/api/{{version}}/Illuminate/Routing/Router.html) | `router`
Schema | [Illuminate\Database\Schema\Blueprint](http://laravel.com/api/{{version}}/Illuminate/Database/Schema/Blueprint.html) |
Session | [Illuminate\Session\SessionManager](http://laravel.com/api/{{version}}/Illuminate/Session/SessionManager.html) | `session`
Session (Instance) | [Illuminate\Session\Store](http://laravel.com/api/{{version}}/Illuminate/Session/Store.html) |
Storage | [Illuminate\Contracts\Filesystem\Factory](http://laravel.com/api/{{version}}/Illuminate/Contracts/Filesystem/Factory.html) | `filesystem`
URL | [Illuminate\Routing\UrlGenerator](http://laravel.com/api/{{version}}/Illuminate/Routing/UrlGenerator.html) | `url`
Validator | [Illuminate\Validation\Factory](http://laravel.com/api/{{version}}/Illuminate/Validation/Factory.html) | `validator`
Validator (Instance) | [Illuminate\Validation\Validator](http://laravel.com/api/{{version}}/Illuminate/Validation/Validator.html) |
View | [Illuminate\View\Factory](http://laravel.com/api/{{version}}/Illuminate/View/Factory.html) | `view`
View (Instance) | [Illuminate\View\View](http://laravel.com/api/{{version}}/Illuminate/View/View.html) |
- 說明
- 翻譯說明
- 發行說明
- 升級說明
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- 錯誤與日志
- 開發環境
- HomeStead
- Valet
- 核心概念
- 服務容器
- 服務提供者
- 門面(facades)
- contracts
- HTTP層
- 路由
- 中間件
- CSRF保護
- 控制器
- 請求
- 響應
- Session
- 表單驗證
- 視圖與模板
- 視圖
- Blade模板
- 本地化
- Javascript與CSS
- 入門指南
- laravel-elixir
- 安全
- 用戶認證
- 用戶授權
- 重置密碼
- API授權
- 加密解密
- 哈希
- 綜合話題
- 廣播系統
- 緩存系統
- 事件系統
- 文件存儲
- 郵件發送
- 消息通知
- 隊列
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent集合
- 修改器
- 序列化
- Artisan控制臺
- Artisan 命令行
- 任務調度
- 測試
- 快速入門
- 應用程序測試
- 數據庫測試
- 模擬器
- 官方擴展包
- Cashier交易包
- Envoy 部署工具
- Passport OAuth 認證
- Scout 全文搜索
- Socialite 社交化登錄
- 附錄
- 集合
- 輔助函數
- 擴展包開發
- 交流說明