问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

thinkphp中的控制器(就是那个继承下来的对象)是不是自动实例化的?

发布网友 发布时间:2022-04-06 00:38

我来回答

2个回答

懂视网 时间:2022-04-06 05:00

在之前的文章中我们简单的梳理了一下容器类,接下来就是对其中一个细节进行深度分析。

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];
}

// thinkApp 从容器标识中获取
if (isset($this->bind[$abstract])) {
// 将thinkApp 复制给$concrete变量
$concrete = $this->bind[$abstract];
// 用于代表匿名函数的类 判断是不是闭包
if ($concrete instanceof Closure) {
$object = $this->invokeFunction($concrete, $vars);
} else {
// $this->name['app'] = thinkApp
$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 = thinkApp
$abstract = isset($this->name[$abstract]) ? $this->name[$abstract] : $abstract;

// 从容器实例中获取 如果存在则直接返回对应的实例 也就是使用注册树模式
if (isset($this->instances[$abstract]) && !$newInstance) {
return $this->instances[$abstract];
}

// thinkApp 从容器标识中获取
// 第二次执行$this->bind['thinkApp']不存在走else
if (isset($this->bind[$abstract])) {
// 将thinkApp 复制给$concrete变量
$concrete = $this->bind[$abstract];
// 用于代表匿名函数的类 判断是不是闭包
if ($concrete instanceof Closure) {
$object = $this->invokeFunction($concrete, $vars);
} else {
// $this->name['app'] = thinkApp
$this->name[$abstract] = $concrete;
// 在执行一次本类的make方法,也就是本方法
// thinkApp
return $this->make($concrete, $vars, $newInstance);
}
} else {
// thinkApp
$object = $this->invokeClass($abstract, $vars);
}

if (!$newInstance) {
// 把创建的容器存起来
//$this->instances['thinkApp'] = $object;
$this->instances[$abstract] = $object;
}

return $object;
}
public function invokeClass($class, $vars = [])
{
try {

/**
* ReflectionClass Object
(
[name] => thinkApp
)
*/
// 这里就是之前文章提到的反射
$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);
}
}
// 通过反射获取thinkApp的构造函数
$constructor = $reflect->getConstructor();

$args = $constructor ? $this->bindParams($constructor, $vars) : [];
// 从给出的参数创建一个新的类实例
return $reflect->newInstanceArgs($args);

} catch (ReflectionException $e) {
throw new ClassNotFoundException('class not exists: ' . $class, $class);
}
}

执行流程图

既然把代码都理清楚了,这时来理一下执行的流程图可以看的更清晰。

坚持学习、坚持写博、坚持分享是咔咔从业以来一直所秉持的信念。希望在偌大互联网中咔咔的文章能带给你一丝丝帮助。我是咔咔,下期见。

热心网友 时间:2022-04-06 02:08

根据URL中提供的控制器,来访问相应控制器的类文件,并自动例化对象并调用对应的方法
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
我网贷一万,手续费300,分24期,每期506.67,请问怎么计算月息,和年利率... 多普达手机铃音多普达手机铃声 【车载软件推荐】有车一族必备软件有哪些?好用的车主必备app 我画画时常被说我画画不动脑筋,弱弱的问一句,画画怎样动脑筋? 三星手机如何设置时间在桌面显示? 精确到十分位,要看小数点右边第一位 对吗 要把一个小数精确到十分位,就要看这个小数的( )A.十分位B.百分位C... 黑米算不算粗粮 存定期协议利率选是还是否? 同城上那些卖二手ndsi的是真的吗? thinkphp 怎么实例化rbac thinkphp5怎么实例化模型 thinkphp create方法 thinkphp 如何将c m a运用到项目中 关于在ThinkPHP中运用setInc和setDec两个函数 微商城 个人中心的【钱包】功能怎么开发 thinkPHP 如何学习thinkPHP Thinkphp怎么批量更新数据 quercus 支持thinkphp吗 如何才能学好thinphp5.0 thinkphp 中有几个exception类 workerman 能在thinkphp的框架上使用吗 php反射在哪些场景有哪些作用? thinkphp怎么隐藏参数变量 thinkphp关联模型condition如何传入动态参数 thinkphp中的函数怎么传多个参数 thinkphp里控制器的方法参数可以接收POST参数么 thinkphp中的函数传递参数问题,求解 thinkphp 自动验证 callback function 传参变量 thinkphp中的commond这个方法是干什么用的,参数怎么写 thinkphp3.2.3 D方法怎么实例化后台模型 关于PHP的ThinkPHP的,如何判断接收到select的值,从而进行查询输出? thinkPHP如何查询一个数据表的数据并自动填写在其他的数据表中 ThinkPHP的扩展是如何实现的? 想求几个thinkphp开发的实例及源码 我是新手 Thinkphp中命名空间是怎么做类文件引入的 linux环境下,thinkphp类实例化显示文件不存在,但在index页面却可以实例化 ThinkPHP模板中如何多次输出同一个值或者输出下一个值? 关于thinkphp3.2.3解析__ROOT__,__PUBLIC__以及在配置文件中自定义的模板常量失败问题 thinkphp怎么解析这个xml thinkphp模板读取数据时怎么解析HTML代码 ThinkPHP的路由解析有什么用?怎么用? thinkphp 怎么解析url的 thinkphp问题 thinkphp 自定义标签函数 怎么解析循环的变量 thinkphp使用literal防止模板标签被解析的方法 有关thinkphp的学习 ThinkPHP如何从访问的IP地址解析其地址(省市) thinkphp把HTML+PHP写的一个页面代码存入数据库以后 读取出来的效果HTML代码解析了PHP代码被直接输出 thinkphp 往数据库存储的是PHP程序代码,在读取出来后不被解析而是直接输出的 有什么办法解决吗