如何处理http请求?
上一篇文章我们讲了thinkphp的容器的实现过程,也知道了http实例的获取来源,接下来就是http开始处理请求了,看代码:
$response = $http->run();
对!你没看错!就这么一行代码!
当然,只是这一行代码肯定没办法处理整个请求逻辑,我们看这行代码之后具体做了什么操作,我们进入Http类,找到run()
这个方法:
/**
* 执行应用程序
* @access public
* @param Request|null $request
* @return Response
*/
public function run(Request $request = null): Response
{
//自动创建request对象
$request = $request ?? $this->app->make('request', [], true);
$this->app->instance('request', $request);
try {
$response = $this->runWithRequest($request);
} catch (Throwable $e) {
$this->reportException($e);
$response = $this->renderException($request, $e);
}
return $response;
}
处理http请求的核心部分
我们看第一行,上一篇文章我们已经分析过make()是如何运行的了,那这行代码我们也就很容易能理解了,这是获取了一个Request类的实例。
然后第二行,我们也分析过instance()这个方法,就是把实例绑定到容器的,也就是说,程序执行到这里的时候,我们的容器里就存入了Request类。
我们继续往下看try中的这行代码:$response = $this->runWithRequest($request);
,这行代码调用了runWithRequest()这个方法,我们看一下这个方法的具体代码:
/**
* 执行应用程序
* @param Request $request
* @return mixed
*/
protected function runWithRequest(Request $request)
{
// 1.调用App类的初始化$this->app->initialize();
$this->initialize();
// 2.加载全局中间件
$this->loadMiddleware();
// 3.监听HttpRun
$this->app->event->trigger(HttpRun::class);
return $this->app->middleware->pipeline()// 4.处理中间件的调度,仔细分析middleware类中的pipeline()方法会发现,这一步会执行中间件
->send($request)// 5.把包含请求数据的$request类初始化进当前执行
->then(function ($request) {
return $this->dispatchToRoute($request);// 6.开始处理路由调度,根据路由找到具体要执行的文件位置:控制器、方法等,执行并返回结果
});
}
上面这个方法就是执行应用程序的具体过程,下面我们会一点一点来分析上面注释中的各个点。
1、注释1:调用App类的初始化
我们找到它调用的App中的方法,看代码:
/**
* 初始化应用
* @access public
* @return $this
*/
public function initialize()
{
$this->initialized = true;
$this->beginTime = microtime(true);
$this->beginMem = memory_get_usage();
// 加载环境变量
if (is_file($this->rootPath . '.env')) {
$this->env->load($this->rootPath . '.env');
}
$this->configExt = $this->env->get('config_ext', '.php');
$this->debugModeInit();
// 加载全局初始化文件
$this->load();
// 加载框架默认语言包
$langSet = $this->lang->defaultLangSet();
$this->lang->load($this->thinkPath . 'lang' . DIRECTORY_SEPARATOR . $langSet . '.php');
// 加载应用默认语言包
$this->loadLangPack($langSet);
// 监听AppInit
$this->event->trigger(AppInit::class);
date_default_timezone_set($this->config->get('app.default_timezone', 'Asia/Shanghai'));
// 初始化
foreach ($this->initializers as $initializer) {
$this->make($initializer)->init($this);
}
return $this;
}
2、注释2:加载全局中间件
3、注释3:监听HttpRun
4、注释4:处理中间件的调度
5、注释5:初始化当前执行的数据
6、注释6:处理路由调度
--未完待续--