The implementation of Facade in thinkphp

Keywords: PHP Session Laravel

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).
Maybe there are a lot of PHP programmers who have been here for 1-5 years. Many friends want to learn more about swoole, laravel and thinkphp6. swoft microservices encounter many difficulties in use. In order to advance PHP architects as soon as possible, you can refer to this PHP architect roadmap and architecture course. Please poke here.

Posted by cloudnyn3 on Mon, 21 Oct 2019 20:15:54 -0700