この記事では、コンテナ (Container) とファサード (Facade) とは何ですか? thinkphp5.1 のコンテナとファサードの簡単な分析は一定の参考値を持っていますので、困っている友人は参考にしていただければ幸いです。
p5.1 では、コンテナ (Container) とファサード (Facade) という 2 つの新しいクラスが導入されました。
公式ドキュメントでは、次の定義が与えられています:
Container (Container) )クラスを一元管理し、オブジェクトインスタンスの一意性を確保します。
Facade は、コンテナー (コンテナー) 内のクラスの静的呼び出しインターフェイスを提供します。従来の静的メソッド呼び出しと比較して、より優れたテスト容易性とスケーラビリティをもたらします。ファサード クラスは、非静的クラス ライブラリで定義できます。
ソース コードを詳しく見て、その実装方法を見てみましょう:
// 在框架目录下的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, ... ]);
コンテナ実装:
ここで、フレームワークは、一般的なシステム クラスをバインドするのに役立ちました。コンテナー 後で使用する場合は、ヘルパー関数 app() を呼び出して、コンテナー内でクラス解析呼び出しを実行するだけで、バインドされたクラス識別子が自動的かつ迅速にインスタンス化されます。
// 实例化缓存类 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); }
つまり、クラスのインスタンス化は、リフレクション クラスまたはクロージャを通じてコンテナ内に実装されます。
ファサード実装:
例を使って分析してみましょう:
facade\Config::get('app_debug');
実装を分析してみましょう:
// thinkphp\library\facade\Config 类
namespace think\facade; use think\Facade; class Config extends Facade { }
// ソース コードからはConfig 自体のメソッドです。これは Facade のメソッドを継承しますが、Facade はこの静的メソッドを取得しません
// この時点で、システムは自動的にマジック メソッド __callStatic() をトリガーし、Facade はこのメソッドを書き換えます:
public static function __callStatic($method, $params) { return call_user_func_array([static::createFacade(), $method], $params); }
// 最後の呼び出しはユーザー定義関数であることがわかります: call_user_func_array([instance, method],parameter). Config インスタンスを取得するために、Facade はオブジェクトを取得するメソッドを定義します:
/** * 创建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); }
// オブジェクトはコンテナを通じて内部でインスタンス化されます
// think\Config クラスが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');
つまり, ファサードはPHPのマジックメソッド__callStaticによって実装され、コンテナと連携して動的クラスの静的呼び出しを実現します。
関連する推奨事項:
thinkphp テンプレート モバイル WeChat 支払いか WeChat スキャン コード支払いかを判断する方法
PHP でページ ジャンプを実現する必要がある機能はどのように機能しますか? (機能ラベルの例)
以上がコンテナとファサードとは何ですか? thinkphp5.1 のコンテナーとファサードの簡単な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。