What is the Facade? At present, it is a class that is used to facilitate the static method call of the original class (undefined static method).
The specific implementation of Facade is as follows:
First look at the core document:
\thinkphp\base.php
`//Register static proxy of core class
Facade::bind([
facade\App::class => App::class, facade\Build::class => Build::class, facade\Cache::class => Cache::class, facade\Config::class => Config::class, facade\Cookie::class => 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 => View::class,]);
You can see the binding method similar to that in the container. Find the corresponding binding method as follows:
` /**
* Static proxy of binding class * @static * @access public * @param string|array $name Class ID * @param string $class Class name * @return object */ public static function bind($name, $class = null) { if (__CLASS__ != static::class) { return self::__callStatic('bind', func_get_args()); } if (is_array($name)) { self::$bind = array_merge(self::$bind, $name); } else { self::$bind[$name] = $class; } }` //You can see that it is also put into an array $bind.
Here, notice the following method of registering class alias in thinkphpbase.php file, which can realize class alias direct access to class (see here for yourself)
`//Register class library alias
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,]);
How to call static methods, such as
\Cache::set('name','value');
For this method, how to call the set method at a specific time? First, use the alias mechanism of the above class to find the corresponding facade cache:: class, which is actually called. Then let's look at the contents of this class:
namespace think\facade; use think\Facade; class Cache extends Facade { }
You can see that there is no content, so where is the set method? Here we use a method that will be called if the static method call of PHP fails. In the Facade class, there are:
// Call the method of the actual class public static function __callStatic($method, $params) { return call_user_func_array([static::createFacade(), $method], $params); } //When an invocation method is invoked in a static context, __callStatic() is called.
In other words, when the set method is not called, the method will be called, that is, it is actually called
call_user_func_array([static::createFacade(), $method], $params)
In fact:
/** * Create a Facade instance * @static * @access protected * @param string $class Class name or ID * @param array $args variable * @param bool $newInstance Whether to create a new instance every time * @return object */ protected static function createFacade($class = '', $args = [], $newInstance = false) { $class = $class ?: static::class; $facadeClass = static::getFacadeClass(); if ($facadeClass) { $class = $facadeClass; } elseif (isset(self::$bind[$class])) { $class = self::$bind[$class]; } if (static::$alwaysNewInstance) { $newInstance = true; } return Container::getInstance()->make($class, $args, $newInstance); }
You can see the last sentence, which is actually the set method of the instance of Cache::class (obtained through the container).