What this article brings to you is about what is a container (Container) and façade (facade)? thinkphp5.1 in the container and the façade of the analysis, there is a certain reference value, there is a need for friends to refer to, I hope you have some help.
The two new classes of containers (Container) and facades (facade) are introduced in p5.1
The official documentation has been defined:
The container (Container) implements the unified management of the class, ensuring the uniqueness of the object instance.
The façade (facade) provides a static calling interface for classes in the container (Container), which brings better testability and extensibility than traditional static method calls, and you can define a facade class for any non-static class library.
In-depth source, let's see how it all came true:
base.php files in the framework directory//Register core class to Container container::getinstance ()->bind ([ ' app ' = app::class, ' build ' = = Build::class, ' cache ' = cache::class, ' config ' = Config::class, ...]; /Register the core class static proxy Facade::bind ([ facade\app::class = app::class, facade\build::class = Build :: Class, facade\cache::class = cache::class, facade\config::class = Config::class, ...]);/ /Register Class Library alias Loader::addclassalias ([ ' App ' = facade\app::class, ' Build ' = facade\build:: Class, ' Cache ' = facade\cache::class, ' Config ' = Facade\config::class, ...];
Container implementations:
Here, the framework has helped us to bind the system to the common class to the container, in the later use, only need to invoke the helper function app () for the class resolution call in the container, for the already bound class identity, will be automatically instantiated quickly.
//instantiate the Cache class app (' cache ');//App (' Cache ', [' file ']), parameterized call//equivalent to execute container:: Get (' cache ');//view the source code, the container call is actually the Make method, in the method called reflection and other implementation class instantiation, the process is as follows:
public function make ($abstract, $vars = [], $newInstance = False) {if (true = = = $vars) {//Always create a new instantiated object $newInstance = true; $vars = []; } if (Isset ($this->instances[$abstract]) && $newInstance) {$object = $this->instances[$abstract] ; } else {if (Isset ($this->bind[$abstract])) {$concrete = $this->bind[$abstract]; Closures implement if ($concrete instanceof \closure) {$object = $this->invokefunction ($concrete, $vars ); } else {$object = $this->make ($concrete, $vars, $newInstance); }} else {//reflection implementation $object = $this->invokeclass ($abstract, $vars); } if (! $newInstance) {$this->instances[$abstract] = $object; }} return $object;}
/** * Invoke reflection Execution Class instantiation support Dependency Injection * @access public * @param string $class class name * @param array $vars variable * @return Mixed */public function Invokeclass ($class, $vars = []) { $reflect = new \reflectionclass ($class); $constructor = $reflect->getconstructor (); if ($constructor) { $args = $this->bindparams ($constructor, $vars); } else { $args = []; } Return $reflect->newinstanceargs ($args);}
/** * Execute function or Closure method support parameter Call * @access public * @param string|array|\closure $function function or closure * @param array $va RS variable * @return mixed */public function invokefunction ($function, $vars = []) { $reflect = new \reflectionfunctio N ($function); $args = $this->bindparams ($reflect, $vars); Return $reflect->invokeargs ($args);}
In short, an instantiation of a class is implemented inside a container through reflection classes or closures.
Façade implementation:
An example is given to analyze:
Facade\config::get (' App_debug ');
Let's analyze how it's implemented:
Thinkphp\library\facade\config class
Namespace Think\facade;use think\facade;class Config extends facade{}
From the source code see Config itself there is no method, it inherits the method of facade, but facade does not have the static method of Get
At this point, the system automatically triggers the Magic method: __callstatic (), facade overrides this method:
public static function __callstatic ($method, $params) { return Call_user_func_array ([Static::createfacade (), $ Method], $params);}
Visible, the last call is a user-defined function: Call_user_func_array ([instance, method], parameter), in order to obtain the config instance, facade also defines a method to get the object:
/** * Create facade instance * @static * @access protected * @param string $class class name or identity * @param array $args Variable * @param bool $newInstance whether to create a new instance each 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);}
Inside it is a container to instantiate the object
Because the Think\config class has been bound to the Config identifier in base.php
Container::getinstance ()->bind ([' config ' = Config::class])//In the Createfacade method, get the name of the class: $class = $class?: Static::class; This is the identity of the CONFIG.
In the container's Make method, according to the Config identifier, locate the bound Think\config class and invoke its dynamic method get. Facade\config::get (' App_debug '); The Last Call is: (New Think\config ())->get (' App_debug ');
In short, the implementation of the façade is through the Magic method of Php __callstatic, and then with the container to implement dynamic class static call.