Home >PHP Framework >ThinkPHP >How does the ThinkPHP container return an instance?
“In the previous article, we briefly sorted out the container class, and the next step is to conduct an in-depth analysis of one of the details.
”
Container instance calls the make method
This article does not have much text analysis, and the execution process is explained in the code comments.
Codestatic::getInstance()
After returning the instance of Container, the make method of this class will be called. The next step is to explain the make method in detail.
Before we start reading the source code in the make method, we need to briefly sort out several attributes.
These four attributes must be somewhat impressive, and instances and instances must be distinguished.
One of these two attributes is the instance of the current class returned by the singleton mode, and the other is all the instances in the container.
First execution result
<span style="display: block; background: url(https://my-wechat.mdnice.com/point.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #282c34; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #282c34; border-radius: 5px;"> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">/**<br/> * 创建类的实例<br/> * <span class="hljs-doctag" style="color: #c678dd; line-height: 26px;">@access</span> public<br/> * <span class="hljs-doctag" style="color: #c678dd; line-height: 26px;">@param</span> string $abstract 类名或者标识<br/> * <span class="hljs-doctag" style="color: #c678dd; line-height: 26px;">@param</span> array|true $vars 变量<br/> * <span class="hljs-doctag" style="color: #c678dd; line-height: 26px;">@param</span> bool $newInstance 是否每次创建新的实例<br/> * <span class="hljs-doctag" style="color: #c678dd; line-height: 26px;">@return</span> object<br/> */</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">public</span> <span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">function</span> <span class="hljs-title" style="color: #61aeee; line-height: 26px;">make</span><span class="hljs-params" style="line-height: 26px;">($abstract, $vars = [], $newInstance = false)</span><br/> </span>{<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 判断$vars这个变量是否为true</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">true</span> === $vars) {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 总是创建新的实例化对象</span><br/> $newInstance = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">true</span>;<br/> $vars = [];<br/> }<br/><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// app 这里就是在容器别名里获取传递过来的app 如果没有则就是app</span><br/> $abstract = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">isset</span>(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->name[$abstract]) ? <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->name[$abstract] : $abstract;<br/> <br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 从容器实例中获取 如果存在则直接返回对应的实例 也就是使用注册树模式</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">isset</span>(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->instances[$abstract]) && !$newInstance) {<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->instances[$abstract];<br/> }<br/><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// think\App 从容器标识中获取</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">isset</span>(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->bind[$abstract])) {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 将think\App 复制给$concrete变量</span><br/> $concrete = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->bind[$abstract];<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 用于代表匿名函数的类 判断是不是闭包</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> ($concrete <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">instanceof</span> Closure) {<br/> $object = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->invokeFunction($concrete, $vars);<br/> } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">else</span> {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// $this->name['app'] = think\App</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->name[$abstract] = $concrete;<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 在执行一次本类的make方法,也就是本方法</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->make($concrete, $vars, $newInstance);<br/> }<br/> } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">else</span> {<br/> $object = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->invokeClass($abstract, $vars);<br/> }<br/><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (!$newInstance) {<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->instances[$abstract] = $object;<br/> }<br/><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> $object;<br/> }<br/></code>
This is the second execution process
<span style="display: block; background: url(https://my-wechat.mdnice.com/point.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #282c34; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #282c34; border-radius: 5px;"> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">public</span> <span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">function</span> <span class="hljs-title" style="color: #61aeee; line-height: 26px;">make</span><span class="hljs-params" style="line-height: 26px;">($abstract, $vars = [], $newInstance = false)</span><br/> </span>{<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 判断$vars这个变量是否为true</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">true</span> === $vars) {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 总是创建新的实例化对象</span><br/> $newInstance = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">true</span>;<br/> $vars = [];<br/> }<br/><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// app 这里就是在容器别名里获取传递过来的app 如果没有则就是app</span><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 第二次执行时 $abstract = think\App</span><br/> $abstract = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">isset</span>(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->name[$abstract]) ? <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->name[$abstract] : $abstract;<br/><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 从容器实例中获取 如果存在则直接返回对应的实例 也就是使用注册树模式</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">isset</span>(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->instances[$abstract]) && !$newInstance) {<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->instances[$abstract];<br/> }<br/><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// think\App 从容器标识中获取</span><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 第二次执行$this->bind['think\App']不存在走else</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">isset</span>(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->bind[$abstract])) {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 将think\App 复制给$concrete变量</span><br/> $concrete = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->bind[$abstract];<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 用于代表匿名函数的类 判断是不是闭包</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> ($concrete <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">instanceof</span> Closure) {<br/> $object = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->invokeFunction($concrete, $vars);<br/> } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">else</span> {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// $this->name['app'] = think\App</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->name[$abstract] = $concrete;<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 在执行一次本类的make方法,也就是本方法</span><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// think\App</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->make($concrete, $vars, $newInstance);<br/> }<br/> } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">else</span> {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// think\App</span><br/> $object = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->invokeClass($abstract, $vars);<br/> }<br/><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (!$newInstance) {<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 把创建的容器存起来</span><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">//$this->instances['think\App'] = $object;</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->instances[$abstract] = $object;<br/> }<br/><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> $object;<br/> }<br/></code>
<span style="display: block; background: url(https://my-wechat.mdnice.com/point.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #282c34; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #282c34; border-radius: 5px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">public</span> <span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">function</span> <span class="hljs-title" style="color: #61aeee; line-height: 26px;">invokeClass</span><span class="hljs-params" style="line-height: 26px;">($class, $vars = [])</span><br/> </span>{<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">try</span> {<br/><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">/**<br/> * ReflectionClass Object<br/> (<br/> [name] => think\App<br/> )<br/> */</span><br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 这里就是之前文章提到的反射</span><br/> $reflect = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">new</span> ReflectionClass($class);<br/><br/><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> ($reflect->hasMethod(<span class="hljs-string" style="color: #98c379; line-height: 26px;">'__make'</span>)) {<br/> $method = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">new</span> ReflectionMethod($class, <span class="hljs-string" style="color: #98c379; line-height: 26px;">'__make'</span>);<br/><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> ($method->isPublic() && $method->isStatic()) {<br/> $args = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->bindParams($method, $vars);<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> $method->invokeArgs(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">null</span>, $args);<br/> }<br/> }<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 通过反射获取think\App的构造函数</span><br/> $constructor = $reflect->getConstructor();<br/><br/> $args = $constructor ? <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->bindParams($constructor, $vars) : [];<br/> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 从给出的参数创建一个新的类实例</span><br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> $reflect->newInstanceArgs($args);<br/><br/> } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">catch</span> (ReflectionException $e) {<br/> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">throw</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">new</span> ClassNotFoundException(<span class="hljs-string" style="color: #98c379; line-height: 26px;">'class not exists: '</span> . $class, $class);<br/> }<br/> }<br/></code>
Execution flow chart
Now that the code has been clarified, let's sort out the execution flow chart to see it more clearly.
“Persistence in learning, persistence in blogging, and persistence in sharing are the beliefs that Kaka has always adhered to since he started working in the industry. I hope that Kaka’s success in the huge Internet The article can bring you a little bit of help. I am Kaka, see you next time.
”
The above is the detailed content of How does the ThinkPHP container return an instance?. For more information, please follow other related articles on the PHP Chinese website!