您的位置:首页 > 编程语言 > PHP开发

Laravel源码入门-启动引导过程(五)$kernel->handle($request)

2017-05-14 17:20 656 查看
接上文,《Laravel源码入门-启动引导过程(四)app/Http/Kernel.php》,说,Kernel 做了两件事,第一个是定义 $bootstraps[],做好了 boot 系统的准备,第二个是定义 各种 middleware,这些都对 $request 进行加工、处理、甄选、判断,最终为可以形成正确的、有效的 $response 做准备,都完成后,进行了 index.php 中的 $kernel->handle($request),返回 $response。

仔细分析发现,public/index.php 中 $kernel 在make() 时,真的只是做了准备,真正的载入环境变量(.env)、根据配置载入 Service Providers 等,实际在 $kernel->handle($request) 语句中进行。先贴出加入测试 echo 记录下的载入过程结果。

// 开始 public/index.php

$app = require_once __DIR__.'/../bootstrap/app.php'

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

start-->$response = $kernel->handle()

// 进入 Illuminate/Foundation/Http/Kernel.php

Foundation/Http/Kernel::handle()
Foundation/Http/Kernel::sendRequestThroughRouter()
Foundation/Http/Kernel::bootstrap()

// 进入 Illumniate/Foundation/Application.php

Foundation/Application::bootstrapWith($bootstrapWith)

Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables

Illuminate\Foundation\Bootstrap\LoadConfiguration
reading config/app.php

Illuminate\Foundation\Bootstrap\HandleExceptions
Illuminate\Foundation\Bootstrap\RegisterFacades
Illuminate\Foundation\Bootstrap\RegisterProviders
Illuminate\Foundation\Bootstrap\BootProviders

// 回到 public/index.php

end<---$response = $kernel->handle()

下面具体看一下 Illuminate\Foundation\Http\Kernel.php 的 handle() 及相关代码片段。

// Illuminate\Foundation\Http\Kernel.php 片段

/**
* The bootstrap classes for the application.
* 引导类,起引导作用的类
*
* @var array
*/
protected $bootstrappers = [
// 载入服务器环境变量(.env 文件)
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
// 载入配置信息(config 目录)
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
// 配置如何处理异常
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
// 注册 Facades
\Illuminate\Foundation\Bootstrap\RegisterFacades::class,
// 注册 Providers
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,
// 启动 Providers
\Illuminate\Foundation\Bootstrap\BootProviders::class,
];

// 此处省略无关代码

/**
* Handle an incoming HTTP request. 处理请求的 handle()
*
* @param  \Illuminate\Http\Request  $request
* @return \Illuminate\Http\Response
*/
public function handle($request)
{
echo 'Foundation/Http/Kernel::handle() <br />';
try {
$request->enableHttpMethodParameterOverride();

// 将请求发送至中间件、路由处理。
$response = $this->sendRequestThroughRouter($request);
} catch (Exception $e) {
$this->reportException($e);

$response = $this->renderException($request, $e);
} catch (Throwable $e) {
$this->reportException($e = new FatalThrowableError($e));

$response = $this->renderException($request, $e);
}

event(new Events\RequestHandled($request, $response));

return $response;
}

/**
* Send the given request through the middleware / router.
* 将请求发送至中间件、路由处理。
*
* @param  \Illuminate\Http\Request  $request
* @return \Illuminate\Http\Response
*/
protected function sendRequestThroughRouter($request)
{
echo 'Foundation/Http/Kernel::sendRequestThroughRouter() <br />';

$this->app->instance('request', $request);

Facade::clearResolvedInstance('request');

// Kernel 要启动引导
$this->bootstrap();

return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}

/**
* Bootstrap the application for HTTP requests.
* 启动引导(requests 驱动)
*
* @return void
*/
public function bootstrap()
{
echo 'Foundation/Http/Kernel::bootstrap() <br />';

if (! $this->app->hasBeenBootstrapped()) {
// 使用 Application 的 bootstrapWith()方法启动引导
// 参数是 Kernel 中的 bootstrapers[]。
$this->app->bootstrapWith($this->bootstrappers());
}
}

=== 总结 ===

如先期描述的 handle() 通过 sendRequestThroughtRouter($request) 处理请求,返回 $response,途中进行了 启动引导,$this->bootstrap(),进一步调用 Application 的 bootstrapWith(),将自己定义的 bootstrapper[] 传入,这个 bootstrappers[] 如前定义,包括了载入服务器环境变量、配置信息、服务提供者、异常处理等。一切结束后,没有抛出异常的话,返回 public/index.php,正如开始的 echo 记录一样。

附:Application 中 bootstrapWith() 代码

// Illuminate\Foundation\Application.php 代码片段

/**
* Run the given array of bootstrap classes.
*
* @param  array  $bootstrappers
* @return void
*/
public function bootstrapWith(array $bootstrappers)
{
echo 'Foundation/Application::bootstrapWith($bootstrapWith) <br />';
$this->hasBeenBootstrapped = true;

foreach ($bootstrappers as $bootstrapper) {
echo $bootstrapper . '<br />';

$this['events']->fire('bootstrapping: '.$bootstrapper, [$this]);

// 解析每个 $bootstrapper,由调用他们自身的 bootstrap(),引导。
$this->make($bootstrapper)->bootstrap($this);

$this['events']->fire('bootstrapped: '.$bootstrapper, [$this]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息