参考
https://sergeyzhuk.me/2016/05...php
Laravel facades serve as "static proxies" to underlying classes in the service container, providing the benefit of a terse, expressive syntax while maintaining more testability and flexibility than traditional static methods.
Laravel 门面为 Laravel 服务的使用提供了便捷方式 ,再也不须要从服务容器中类型提示和契约解析便可直接经过静态门面调用.laravel
能够理解为操做复杂对象的简化方法,就是外观模式里的外观类的方法.express
对应设计模式里的外观模式,对类实例的方法的封装,使用起来更方便.设计模式
下面三种方法对某个实例方法来说没有区别:app
//facade SomeService::someMethod(); // and app()->make('some.service')->someMethod(); // or App::make('some.service')->someMethod();
核心是php的魔术方法__callStacic
,全部调用Facade里静态方法,都会进入这个函数,进行真正的(代理)调用.函数
//Facde接口 public static function __callStatic($method, $args) { $instance = static::getFacadeRoot(); if (! $instance) { throw new RuntimeException('A facade root has not been set.'); } return $instance->$method(...$args); } public static function getFacadeRoot() { return static::resolveFacadeInstance(static::getFacadeAccessor()); } protected static function resolveFacadeInstance($name) { if (is_object($name)) { return $name; } if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } //核心就在这,$app就是上面的ioc容器实例 if (static::$app) { return static::$resolvedInstance[$name] = static::$app[$name]; } //真正的实例来源 public static function swap($instance) { static::$resolvedInstance[static::getFacadeAccessor()] = $instance; if (isset(static::$app)) { //注册到Ioc容器 static::$app->instance(static::getFacadeAccessor(), $instance); } } }
实现Facade接口的类,要实现getFacadeAccessor
和resolveFacadeInstance
,关联要真正的实例.测试
Date为例子,其真正的实例是DateFactory
.flex
class Date extends Facade { const DEFAULT_FACADE = DateFactory::class; /** * Get the registered name of the component. * * @return string * * @throws \RuntimeException */ protected static function getFacadeAccessor() { return 'date'; } /** * Resolve the facade root instance from the container. * * @param string $name * @return mixed */ protected static function resolveFacadeInstance($name) { if (! isset(static::$resolvedInstance[$name]) && ! isset(static::$app, static::$app[$name])) { $class = static::DEFAULT_FACADE; //swap执行真正的instance绑定到ioc容器 static::swap(new $class); } return parent::resolveFacadeInstance($name); } }
想用Date时,能够:设计
//直接用门面静态方法 \Illuminate\Support\Facades\Date::createXXX()
但Laravel 的门面做为服务容器中底层类的「静态代理」,相比于传统静态方法,在维护时可以提供更加易于测试、更加灵活、简明优雅的语法。代理
若是仍是嫌弃用以前use xxxx\Facades\xx
太麻烦,config.app里配置个alias:
?php return [ //... 'aliases' => [ 'App' => Illuminate\Support\Facades\App::class, 'Artisan' => Illuminate\Support\Facades\Artisan::class, 'Auth' => Illuminate\Support\Facades\Auth::class, 'Blade' => Illuminate\Support\Facades\Blade::class, 'Bus' => Illuminate\Support\Facades\Bus::class, 'Cache' => Illuminate\Support\Facades\Cache::class, 'Config' => Illuminate\Support\Facades\Config::class, ], // ... ];
直接用就行了:
Cache::get(...);