ThinkPHP Framework ——十年匠心的高性能PHP框架 http://www.thinkphp.cn
前言
最近打算对ThinkPHP v6.0
进行一些简单的了解,先从入口文件的启动流程开始分析
介绍
- 实例化
App
并获取Web应用管理类http
组件-
http->run
-
http->runWithRequest
-
http->dispatchToRoute
-
route->dispatch
-
Dispatch->run
-
Object->exec
根据当前请求类型分别调用组件的exec
方法-
Controller->exec
这是Web
控制器的exec
实现-
App->invokeReflectMethod
调用控制器方法 -
Dispatch->autoResponse($data);
响应数据
-
-
-
-
-
-
-
return $response
-
- 处理数据并响应
入口文件
public/index.php
<?php
namespace think;
require __DIR__ . '/../vendor/autoload.php';
// 执行HTTP应用并响应
$http = (new App())->http;
$response = $http->run();
$response->send();
$http->end($response);
引入自动加载vendor/autoload.php
实例化App
对象并获取http
实例
通过App
继承的Container
类中的__get
魔术方法获取http
实例
这部分算是容器组件管理,框架里大部分的组件都是以此形式进行动态实例化(服务定位器+单例模式),不想了解的可以先跳过
Container.php
类的魔术方法__get
...
public function __get($name)
{
return $this->get($name);
}
get
、has
、bound
方法
App
基础类中预定义了一系列的容器绑定,详见App->$bind
成员,其中http
对应的是think\Http
类
/**
* 获取容器中的对象实例
* @access public
* @param string $abstract 类名或者标识
* @return object
*/
public function get($abstract)
{
if ($this->has($abstract)) {
return $this->make($abstract);
}
throw new ClassNotFoundException('class not exists: ' . $abstract, $abstract);
}
/**
* 判断容器中是否存在类及标识
* @access public
* @param string $name 类名或者标识
* @return bool
*/
public function has($name): bool
{
return $this->bound($name);
}
/**
* 判断容器中是否存在类及标识
* @access public
* @param string $abstract 类名或者标识
* @return bool
*/
public function bound(string $abstract): bool
{
return isset($this->bind[$abstract]) || isset($this->instances[$abstract]);
}
make
方法,这里是关键。会调用invokeClass
方法以反射形式进行实例化,这里只是简单介绍下,详细的会在后续容器管理篇Container
进行介绍
/**
* 创建类的实例 已经存在则直接获取
* @access public
* @param string $abstract 类名或者标识
* @param array $vars 变量
* @param bool $newInstance 是否每次创建新的实例
* @return mixed
*/
public function make(string $abstract, array $vars = [], bool $newInstance = false)
{
$abstract = $this->getAlias($abstract);
if (isset($this->instances[$abstract]) && !$newInstance) {
return $this->instances[$abstract];
}
if (isset($this->bind[$abstract]) && $this->bind[$abstract] instanceof Closure) {
$object = $this->invokeFunction($this->bind[$abstract], $vars);
} 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(string $class, array $vars = [])
{
try {
$reflect = new ReflectionClass($class);
} catch (ReflectionException $e) {
throw new ClassNotFoundException('class not exists: ' . $class, $class, $e);
}
if ($reflect->hasMethod('__make')) {
$method = $reflect->getMethod('__make');
if ($method->isPublic() && $method->isStatic()) {
$args = $this->bindParams($method, $vars);
return $method->invokeArgs(null, $args);
}
}
$constructor = $reflect->getConstructor();
$args = $constructor ? $this->bindParams($constructor, $vars) : [];
$object = $reflect->newInstanceArgs($args);
// !!!这里有彩蛋
$this->invokeAfter($class, $object);
return $object;
}
至此,http
组件的实例化大致介绍完成
接下来就是对请求的处理
- 调用
$http->run
- 获取
request
实例- 执行应用程序
runWithRequest
- !!!(主要处理过程)
runWithRequest - 执行应用请求
返回`response`实例
输出响应$http->end($response)