介绍
Facades 为应用的 IoC container 的类提供了一个静态的接口。Laravel 里面自带了一些 Facades,其实你应该已经用到它们了,不过可能还不知道它们是什么。Laravel 的 Facades 像是 Ioc container 类的静态代理,比起传统的静态方法(Static methods),Facades 更简洁,也更容易表达,更具可测性(Testability)与灵活性(Flexibility)。
有时候你可能需要为你的应用跟包去创建自己的 Facades,下面我们就一起去看一下相关的概念,开发,还有这些类的用法。
注意:在了解 Facades 之前,你最好先了解一下 Laravel 里的 Ioc Container 。
解释
在 Laravel 应用这个上下文里面,一个 Facade 就是一个类,使用这个类可以访问到来自容器里的一个对象,这个功能就是在 Facade 类里面定义的。Laravel 的 Facades 还有任何你自己定义的 Facades,都会去继承 Facade 这个类。
你的 Facade 类只需要实施一个的方法:getFacadeAccessor。要在容器里 resolve 什么出来,都是在这个方法里去做的。Facade 这个基类里面使用了 __callStatic() 魔术方法,可以延迟到 resolved 对象上的,来自 Facade 的调用。
所以,当你使用 Facade 调用的时候,比如像这样:Cache:get,laravel 会从 Ioc container 里面 resolves 缓存管理类,然后再去调用这个类上面的 get 方法。Laravel 的 Facades 可以去定位服务,它是一种使用 Laravel 的 Ioc container 的更方便的语法。
实际应用
下面的例子,去调用了一下 Laravel 的缓存系统。先看一下下面这行代码,你可能会觉得,这是直接去调用 Cache 这个类上面的一个叫 get 的静态的方法。
$value = Cache::get('key');
不过,如果你查看 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 这个基类,它里面定义了一个叫 getFacadeAccessor() 的方法。注意,这个方法的干的事就是去返回一个 Ioc 绑定的名字,这里就是 cache。
当用户在引用任何在 Cache 这个 Facade 上的静态方法的时候,Laravel 就会从 Ioc container 里面去 resolves cache 这个绑定,并且会去执行在对象上的这个所请求的方法(这里就是 get 这个方法)。
所以,我们在调用 Cache::get 的时候,它的真正的意思是这样的:
$value = $app->make('cache')->get('key');
导入 Facades
注意,在使用 facade 的时候,如果控制器里面用到了命名空间,你需要把 Facade 类导入到这个命名空间里。所有的 Facades 都是在全局命名空间下:
<?php namespace App\Http\Controllers; use Cache; class PhotosController extends Controller { /** * Get all of the application photos. * * @return Response */ public function index() { $photos = Cache::get('photos'); // } }
创建 Facades
为自己的应用或者包去创建 Facade 只需要三个东西:
- 一个 IoC 绑定。
- 一个 Facade 类。
- 一个 Facade 别名的配置。
下面来看一下例子。在下面我们定义了一个类:PaymentGateway\Payment 。
namespace PaymentGateway;
class Payment {
public function process()
{
//
}
}
我们需要能在 Ioc container 里面去 resolve 这个类。所以,先要去添加一个 Service Provider 绑定:
App::bind('payment', function() { return new \PaymentGateway\Payment; });
去注册这个绑定最好的方法就是去创建一个新的 Service Provider ,把它命名为 PaymentServiceProvider ,然后把它绑定到 register 方法上。再去配置 laravel 在 config/app.php 这个配置文件里加载你的 Service Provider 。
下一步就是去创建自己的 Facade 类:
use Illuminate\Support\Facades\Facade; class Payment extends Facade { protected static function getFacadeAccessor() { return 'payment'; } }
最后,如果你愿意,可以去给 Facade 添加一个别名,放到 config/app.php 配置文件里的 aliases 数组里。现在,我们就可以去调用 Payment 类的一个实例上的 process 这个方法了。像这样:
Payment::process();
自动加载别名
在 aliases 数组里的类,在有些实例上是不可用的,这是因为 PHP 不会试图去自动加载未定义的 type-hint 的类。如果ApiTimeoutException 是 \ServiceWrapper\ApiTimeoutException 的别名,有个 catch(ApiTimeoutException $e) 在 \ServiceWrapper 这个命名空间以外,这就永远不会收到异常,甚至是抛出来的异常也不会接收到。类似的问题还出现在 type hint 到有别名的类里面。解决的办法只有放弃别名,并且在需要它们的每个文件的顶部, use 你想 type hint 的类。
Mocking Facades
单元测试是 Facades 为什么会存在的一个很主要的原因。了解更多,可以查看文档里的 mocking facades (英文文档)这个单元。
Facade 类参考
在下面你可以找到所有的 Facade ,还有在它下面表示的类。
Laravel Laravel5 中文手册 Facade
评论
你在百度竞价的lavarel课程,着陆页提示网站遇到不可知的错误!我就是一个无聊胡乱逛网站的人,不是我故意点的链接,我只是好奇!!!希望你修改下,要不然就白白浪费钱了!!!
9 年 2 个月 以前
谢了 :)
9 年 2 个月 以前
哈哈,应该是我谢你。我从你这里学到很多东西!!!
9 年 2 个月 以前