ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# 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\\Appthink\\facade\\Appthink\\Buildthink\\facade\\Buildthink\\Cachethink\\facade\\Cachethink\\Configthink\\facade\\Configthink\\Cookiethink\\facade\\Cookiethink\\Debugthink\\facade\\Debugthink\\Envthink\\facade\\Envthink\\Hookthink\\facade\\Hookthink\\Langthink\\facade\\Langthink\\Logthink\\facade\\Logthink\\Middlewarethink\\facade\\Middlewarethink\\Requestthink\\facade\\Requestthink\\Responsethink\\facade\\Responsethink\\Routethink\\facade\\Routethink\\Sessionthink\\facade\\Sessionthink\\Urlthink\\facade\\Urlthink\\Validatethink\\facade\\Validatethink\\Viewthink\\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类Appthink\\facade\\AppBuildthink\\facade\\BuildCachethink\\facade\\CacheConfigthink\\facade\\ConfigCookiethink\\facade\\CookieDbthink\\DbDebugthink\\facade\\DebugEnvthink\\facade\\EnvHookthink\\facade\\HookLangthink\\facade\\LangLogthink\\facade\\LogMiddlewarethink\\facade\\MiddlewareRequestthink\\facade\\RequestResponsethink\\facade\\ResponseRoutethink\\facade\\RouteSessionthink\\facade\\SessionUrlthink\\facade\\UrlValidatethink\\facade\\ValidateViewthink\\facade\\View因此前面的代码可以改成 ``` \Cache::set('name','value'); echo \Cache::get('name'); ``` > Facade类定义了一个实例化的`instance`方法,如果你的类也有定义的话将会失效。