ThinkPHP容器之容器是如何返回实例的
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了ThinkPHP容器之容器是如何返回实例的,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5245字,纯文字阅读大概需要8分钟。
内容图文
![ThinkPHP容器之容器是如何返回实例的](/upload/InfoBanner/zyjiaocheng/276/2935bf6011eb4743a6f164040f02ec84.jpg)
“在之前的文章中我们简单的梳理了一下容器类,接下来就是对其中一个细节进行深度分析。
”
Container实例调用make方法
本文没有太多文字解析,都在代码注释中说明了执行过程。
代码static::getInstance()
返回了Container的实例后,就会去调用本类的make方法,接下来就是对make方法进行详解了。
在开始阅读make方法里边的源码之前,我们需要先对几个属性进行简单的梳理一下。
这四个属性一定要有点印象,并且一定要区别instance和instances。
这俩个属性一个是单例模式返回当前类的实例,一个是容器中的所有的实例。
第一次执行结果
/**
* 创建类的实例
* @access public
* @param string $abstract 类名或者标识
* @param array|true $vars 变量
* @param bool $newInstance 是否每次创建新的实例
* @return object
*/
public function make($abstract, $vars = [], $newInstance = false)
{
// 判断$vars这个变量是否为true
if (true === $vars) {
// 总是创建新的实例化对象
$newInstance = true;
$vars = [];
}
// app 这里就是在容器别名里获取传递过来的app 如果没有则就是app
$abstract = isset($this->name[$abstract]) ? $this->name[$abstract] : $abstract;
// 从容器实例中获取 如果存在则直接返回对应的实例 也就是使用注册树模式
if (isset($this->instances[$abstract]) && !$newInstance) {
return $this->instances[$abstract];
}
// think\App 从容器标识中获取
if (isset($this->bind[$abstract])) {
// 将think\App 复制给$concrete变量
$concrete = $this->bind[$abstract];
// 用于代表匿名函数的类 判断是不是闭包
if ($concrete instanceof Closure) {
$object = $this->invokeFunction($concrete, $vars);
} else {
// $this->name['app'] = think\App
$this->name[$abstract] = $concrete;
// 在执行一次本类的make方法,也就是本方法
return $this->make($concrete, $vars, $newInstance);
}
} else {
$object = $this->invokeClass($abstract, $vars);
}
if (!$newInstance) {
$this->instances[$abstract] = $object;
}
return $object;
}
这是第二次执行流程
public function make($abstract, $vars = [], $newInstance = false)
{
// 判断$vars这个变量是否为true
if (true === $vars) {
// 总是创建新的实例化对象
$newInstance = true;
$vars = [];
}
// app 这里就是在容器别名里获取传递过来的app 如果没有则就是app
// 第二次执行时 $abstract = think\App
$abstract = isset($this->name[$abstract]) ? $this->name[$abstract] : $abstract;
// 从容器实例中获取 如果存在则直接返回对应的实例 也就是使用注册树模式
if (isset($this->instances[$abstract]) && !$newInstance) {
return $this->instances[$abstract];
}
// think\App 从容器标识中获取
// 第二次执行$this->bind['think\App']不存在走else
if (isset($this->bind[$abstract])) {
// 将think\App 复制给$concrete变量
$concrete = $this->bind[$abstract];
// 用于代表匿名函数的类 判断是不是闭包
if ($concrete instanceof Closure) {
$object = $this->invokeFunction($concrete, $vars);
} else {
// $this->name['app'] = think\App
$this->name[$abstract] = $concrete;
// 在执行一次本类的make方法,也就是本方法
// think\App
return $this->make($concrete, $vars, $newInstance);
}
} else {
// think\App
$object = $this->invokeClass($abstract, $vars);
}
if (!$newInstance) {
// 把创建的容器存起来
//$this->instances['think\App'] = $object;
$this->instances[$abstract] = $object;
}
return $object;
}
public function invokeClass($class, $vars = [])
{
try {
/**
* ReflectionClass Object
(
[name] => think\App
)
*/
// 这里就是之前文章提到的反射
$reflect = new ReflectionClass($class);
if ($reflect->hasMethod('__make')) {
$method = new ReflectionMethod($class, '__make');
if ($method->isPublic() && $method->isStatic()) {
$args = $this->bindParams($method, $vars);
return $method->invokeArgs(null, $args);
}
}
// 通过反射获取think\App的构造函数
$constructor = $reflect->getConstructor();
$args = $constructor ? $this->bindParams($constructor, $vars) : [];
// 从给出的参数创建一个新的类实例
return $reflect->newInstanceArgs($args);
} catch (ReflectionException $e) {
throw new ClassNotFoundException('class not exists: ' . $class, $class);
}
}
执行流程图
既然把代码都理清楚了,这时来理一下执行的流程图可以看的更清晰。
“坚持学习、坚持写博、坚持分享是咔咔从业以来一直所秉持的信念。希望在偌大互联网中咔咔的文章能带给你一丝丝帮助。我是咔咔,下期见。
”
以上就是ThinkPHP容器之容器是如何返回实例的的详细内容。
本文系统来源:https://www.php.cn/phpkj/thinkphp/461077.html内容总结
以上是互联网集市为您收集整理的ThinkPHP容器之容器是如何返回实例的全部内容,希望文章能够帮你解决ThinkPHP容器之容器是如何返回实例的所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。