加载中...

Facade


门面(Facade

门面为容器中的类提供了一个静态调用接口,相比于传统的静态方法调用, 带来了更好的可测试性和扩展性,你可以为任何的非静态类库定义一个facade类。

系统已经为大部分核心类库定义了Facade,所以你可以通过Facade来访问这些系统类,当然也可以为你的应用类库添加静态代理。

下面是一个示例,假如我们定义了一个app\common\Test类,里面有一个hello动态方法。

<?php
namespace app\common;

class Test
{
    public function hello($name)
    {
        return 'hello,' . $name;
    }
}

调用hello方法的代码应该类似于:

$test = new \app\common\Test;
echo $test->hello('thinkphp'); // 输出 hello,thinkphp

接下来,我们给这个类定义一个静态代理类app\facade\Test(这个类名不一定要和Test类一致,但通常为了便于管理,建议保持名称统一)。

<?php
namespace app\facade;

use think\Facade;

class Test extends Facade
{
    protected static function getFacadeClass()
    {
        return 'app\common\Test';
    }
}

只要这个类库继承think\Facade,就可以使用静态方式调用动态类app\common\Test的动态方法,例如上面的代码就可以改成:

// 无需进行实例化 直接以静态方法方式调用hello
echo \app\facade\Test::hello('thinkphp');

结果也会输出 hello,thinkphp

说的直白一点,Facade功能可以让类无需实例化而直接进行静态方式调用。

如果没有通过getFacadeClass方法显式指定要静态代理的类,可以在调用的时候进行动态绑定:

<?php
namespace app\facade;

use think\Facade;

class Test extends Facade
{
}
use app\facade\Test;
use think\Facade;

Facade::bind('app\facade\Test', 'app\common\Test');
echo Test::hello('thinkphp');

bind方法支持批量绑定,因此你可以在应用的公共函数文件中统一进行绑定操作,例如:

Facade::bind([
    'app\facade\Test' => 'app\common\Test',
    'app\facade\Info' => 'app\common\Info',
]);

核心Facade类库

系统给内置的常用类库定义了Facade类库,包括:

(动态)类库 Facade类
think\App think\facade\App
think\Build think\facade\Build
think\Cache think\facade\Cache
think\Config think\facade\Config
think\Cookie think\facade\Cookie
think\Debug think\facade\Debug
think\Env think\facade\Env
think\Hook think\facade\Hook
think\Lang think\facade\Lang
think\Log think\facade\Log
think\Middleware think\facade\Middleware
think\Request think\facade\Request
think\Response think\facade\Response
think\Route think\facade\Route
think\Session think\facade\Session
think\Url think\facade\Url
think\Validate think\facade\Validate
think\View think\facade\View

所以你无需进行实例化就可以很方便的进行方法调用,例如:

use think\facade\Cache;

Cache::set('name','value');
echo Cache::get('name');

think\Db类的实现本来就类似于Facade机制,所以不需要再进行静态代理就可以使用静态方法调用(确切的说Db类是没有方法的,都是调用的Query类的方法)。

在进行依赖注入的时候,请不要使用Facade类作为类型约束,而是建议使用原来的动态类,下面是错误的用法:

<?php
namespace app\index\controller;

use think\facade\App;

class Index
{
    public function index(App $app)
    {
    }
}

应当使用下面的方式:

<?php
namespace app\index\controller;

use think\App;

class Index
{
    public function index(App $app)
    {
    }
}

为了更加方便的使用系统类库,系统还给这些常用的核心类库的Facade类注册了类库别名,当进行静态调用的时候可以直接使用简化的别名进行调用。

别名类 对应Facade类
App think\facade\App
Build think\facade\Build
Cache think\facade\Cache
Config think\facade\Config
Cookie think\facade\Cookie
Db think\Db
Debug think\facade\Debug
Env think\facade\Env
Hook think\facade\Hook
Lang think\facade\Lang
Log think\facade\Log
Middleware think\facade\Middleware
Request think\facade\Request
Response think\facade\Response
Route think\facade\Route
Session think\facade\Session
Url think\facade\Url
Validate think\facade\Validate
View think\facade\View

因此前面的代码可以改成

\Cache::set('name','value');
echo \Cache::get('name');

Facade类定义了一个实例化的instance方法,如果你的类也有定义的话将会失效。


还没有评论.