Cet article vous explique qu'est-ce qu'un conteneur (Container) et une façade (Facade) ? La brève analyse des conteneurs et des façades dans thinkphp5.1 a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer, j'espère qu'elle vous sera utile.
P5.1 a introduit deux nouvelles classes, conteneur (Container) et façade (Facade)
Le document officiel a donné la définition :
Conteneur (Container) pour obtenir un résultat unifié. gestion des classes et garantir l’unicité des instances d’objets.
Facade fournit une interface d'appel statique pour les classes du conteneur (Container). Par rapport à l'appel de méthode statique traditionnelle, elle apporte une meilleure testabilité et évolutivité. Vous pouvez définir une classe de façade.
En approfondissant le code source, examinons comment il est implémenté :
// 在框架目录下的base.php文件 // 注册核心类到容器 Container::getInstance()->bind([ 'app' => App::class, 'build' => Build::class, 'cache' => Cache::class, 'config' => Config::class, ... ]); // 注册核心类的静态代理 Facade::bind([ facade\App::class => App::class, facade\Build::class => Build::class, facade\Cache::class => Cache::class, facade\Config::class => Config::class, ... ]); // 注册类库别名 Loader::addClassAlias([ 'App' => facade\App::class, 'Build' => facade\Build::class, 'Cache' => facade\Cache::class, 'Config' => facade\Config::class, ... ]);
Implémentation du conteneur :
Ici, le framework nous a aidé à lier le système commun classes dans le conteneur. Lorsque vous l'utiliserez plus tard, il vous suffit d'appeler la fonction d'assistance app() pour effectuer l'analyse de classe dans le conteneur. L'identifiant de classe lié sera automatiquement et rapidement instancié.
// 实例化缓存类 app('cache'); // app('cache', ['file']); 参数化调用 // 相当于执行了 Container::get('cache'); // 查看源码,Container调用的其实是make方法,在该方法里调用反射等实现类的实例化,过程如下:
public function make($abstract, $vars = [], $newInstance = false) { if (true === $vars) { // 总是创建新的实例化对象 $newInstance = true; $vars = []; } if (isset($this->instances[$abstract]) && !$newInstance) { $object = $this->instances[$abstract]; } else { if (isset($this->bind[$abstract])) { $concrete = $this->bind[$abstract]; // 闭包实现 if ($concrete instanceof \Closure) { $object = $this->invokeFunction($concrete, $vars); } else { $object = $this->make($concrete, $vars, $newInstance); } } else { // 反射实现 $object = $this->invokeClass($abstract, $vars); } if (!$newInstance) { $this->instances[$abstract] = $object; } } return $object; }
/** * 调用反射执行类的实例化 支持依赖注入 * @access public * @param string $class 类名 * @param array $vars 变量 * @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); }
/** * 执行函数或者闭包方法 支持参数调用 * @access public * @param string|array|\Closure $function 函数或者闭包 * @param array $vars 变量 * @return mixed */ public function invokeFunction($function, $vars = []) { $reflect = new \ReflectionFunction($function); $args = $this->bindParams($reflect, $vars); return $reflect->invokeArgs($args); }
En bref, l'instanciation des classes est implémentée à l'intérieur du conteneur via des classes de réflexion ou des fermetures.
Mise en œuvre de la façade :
Analysons-la avec un exemple :
facade\Config::get('app_debug');
Analysons sa mise en œuvre :
// thinkphp\library\facade\Config 类
namespace think\facade; use think\Facade; class Config extends Facade { }
// D'après le code source, Config lui-même n'a aucune méthode. Il hérite des méthodes de Facade, mais Facade n'a pas la méthode statique de get
// A ce moment, le système déclenche automatiquement la méthode magique : __callStatic() , Facade a réécrit cette méthode :
public static function __callStatic($method, $params) { return call_user_func_array([static::createFacade(), $method], $params); }
// On voit que le dernier appel est la fonction définie par l'utilisateur : call_user_func_array([instance, méthode], paramètre). Instance de configuration, Facade définit un objet d'acquisition Méthode :
/** * 创建Facade实例 * @static * @access protected * @param string $class 类名或标识 * @param array $args 变量 * @param bool $newInstance 是否每次创建新的实例 * @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); }
// En interne, l'objet est instancié via le conteneur
// Parce que la classe thinkConfig a été liée à l'identifiant de configuration dans base.php
Container::getInstance()->bind([ 'config' => Config::class ]) // 在 createFacade 方法中,获取类的名称:$class = $class ?: static::class; 即得到 config 这个标识
// 在容器的make方法中,根据config标识,找到绑定的 think\Config 类,并调用其动态方法 get。 facade\Config::get('app_debug'); // 最后调用的是: (new think\Config())->get('app_debug');
En bref, la façade est implémentée via la méthode magique de PHP __callStatic, puis coopère avec le conteneur pour réaliser des appels statiques de classes dynamiques.
Recommandations associées :
PHP veut réaliser saut de page Comment fonctionne la fonction ? (Exemple de balise de fonction)
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!