Facade。目前是一个类,用来实现原类的静态方法(未定义的静态方法)来调用相应的方法。Facade的具体实现如下:先看核心文件:\thinkphp\base.php`//注册核心类Facade::bind([facade\App::class=>App::类,门面\构建::类=>构建::类,门面\缓存::类=>缓存::类,门面\配置::类=>配置::类,门面\Cookie::类=>饼干::class,facade\Debug::class=>Debug::class,facade\Env::class=>Env::class,facade\Hook::class=>Hook::class,facade\Lang::class=>Lang::class,facade\Log::class=>Log::class,facade\Request::class=>Request::class,facade\Response::class=>Response::class,facade\Route::class=>Route::class,facade\Session::class=>Session::class,facade\Url::class=>Url::class,facade\Validate::class=>Validate::class,facade\View::class=>视图::class,]);可以看到类似容器的绑定方法,找到对应的绑定方法如下:`/***绑定类的静态代理*@static*@accesspublic*@paramstring|array$nameclassidentifier*@paramstring$class类名*@returnobject*/publicstaticfunctionbind($name,$class=null){if(__CLASS__!=static::class){returnself::__callStatic('bind',func_get_args());}}if(is_array($name)){self::$bind=array_merge(self::$bind,$name);}else{self::$bind[$name]=$class;}}`可以看到也是放在一个数组$bind中这里注意在thinkphpbase.php文件中注册类名的方法如下,可以实现类名直接访问类(这里自己写)`//注册类库别名Loader::addClassAlias(['App'=>facade\App::class,'Build'=>facade\Build::class,'Cache'=>facade\Cache::class,'Config'=>facade\Config::class,'Cookie'=>facade\Cookie::class,'Db'=>Db::class,'Debug'=>facade\Debug::class,'Env'=>facade\Env::class,'Facade'=>Facade::class,'Hook'=>facade\Hook::class,'Lang'=>facade\Lang::class,'Log'=>facade\Log::class,'Request'=>facade\Request::class,'Response'=>facade\Response::class,'Route'=>facade\Route::class,'Session'=>facade\Session::class,'Url'=>facade\Url::class,'Validate'=>facade\Validate::class,'View'=>facade\View::class,]);那么如何调用静态方法,如\Cache::set('name','value');这个方法,具体时候怎么调用set方法,首先利用上面类的别名机制,直接找到对应的facadeCache::class类,也就是真正调用的类。然后我们看这个类的内容:namespacethink\facade;使用think\Facade;classCacheextendsFacade{}可以看到没有内容,那么set方法从哪里来呢?这里,一个PHP静态方法调用失败,会调用Facade类中的方法://调用实际类的方法publicstaticfunction__callStatic($method,$params){returncall_user_func_array([static::createFacade(),$方法],$参数);}//__callStatic()在静态上下文中调用不可访问的方法时调用。即当无法调用set方法时,会调用该方法,即调用call_user_func_array([static::createFacade(),$method],$params):/***创建Facade实例*@static*@accessprotected*@paramstring$class类名或标识*@paramarray$args变量*@parambool$newInstance是否每次都创建一个新实例*@returnobject*/protectedstaticfunctioncreateFacade($class='',$args=[],$newInstance=false){$class=$class?:static::class;$facadeClass=static::getFacadeClass();如果($facadeClass){$class=$facadeClass;}elseif(isset(self::$bind[$class])){$class=self::$bind[$class];}if(static::$alwaysNewInstance){$newInstance=true;}返回容器::getInstance()->make($class,$args,$newInstance);}可以看到最后一句,其实是调用了Cache::class实例的set方法(通过容器获取)。
