Laravel 13 请求处理流程深度解析

理解 Laravel 的请求处理流程对于构建高性能应用至关重要。本文将深入剖析 Laravel 13 的请求生命周期。

请求生命周期概览

入口文件

1
2
3
4
5
6
7
8
9
10
11
<?php

use Illuminate\Http\Request;

define('LARAVEL_START', microtime(true));

require __DIR__ . '/../vendor/autoload.php';

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

$app->handleRequest(Request::capture());

应用引导

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

namespace Bootstrap;

use Illuminate\Foundation\Application;

$app = new Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);

$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);

$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);

$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);

return $app;

HTTP Kernel

Kernel 结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];

protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],

'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];

protected $middlewareAliases = [
'auth' => \App\Http\Middleware\Authenticate::class,
'cache' => \Illuminate\Routing\Middleware\CacheControl::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
}

请求处理流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php

namespace Illuminate\Foundation\Http;

class Kernel implements KernelContract
{
public function handle($request)
{
$this->requestStartedAt = Carbon::now();

try {
$request->enableHttpMethodParameterOverride();

$response = $this->sendRequestThroughRouter($request);
} catch (Throwable $e) {
$this->reportException($e);

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

$this->app['events']->dispatch(
new RequestHandled($request, $response)
);

return $response;
}

protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request);

Facade::clearResolvedInstance('request');

$this->bootstrap();

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

路由分发

路由匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php

namespace Illuminate\Routing;

class Router
{
public function dispatch(Request $request)
{
$this->currentRequest = $request;

return $this->dispatchToRoute($request);
}

public function dispatchToRoute(Request $request)
{
return $this->runRoute($request, $this->findRoute($request));
}

protected function findRoute($request)
{
$this->routes->match($request);

$this->container->instance(Route::class, $route = $this->routes->match($request));

return $route;
}

protected function runRoute(Request $request, Route $route)
{
$request->setRouteResolver(function () use ($route) {
return $route;
});

$this->events->dispatch(new Events\RouteMatched($route, $request));

return $this->prepareResponse($request,
$this->runRouteWithinStack($route, $request)
);
}
}

路由中间件管道

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php

namespace Illuminate\Routing;

class Router
{
protected function runRouteWithinStack(Route $route, Request $request)
{
$shouldSkipMiddleware = $this->container->bound('middleware.disable') &&
$this->container->make('middleware.disable') === true;

$middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route);

return (new Pipeline($this->container))
->send($request)
->through($middleware)
->then(function ($request) use ($route) {
return $route->run();
});
}

public function gatherRouteMiddleware(Route $route)
{
$middleware = $route->gatherMiddleware();

$excluded = collect($route->excludedMiddleware())->map(function ($name) {
return (array) MiddlewareNameResolver::resolve(
$name, $this->middleware, $this->middlewareGroups
);
})->flatten()->values()->all();

return array_diff($middleware, $excluded);
}
}

控制器执行

控制器调度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php

namespace Illuminate\Routing;

class ControllerDispatcher
{
public function dispatch(Route $route, $controller, $method)
{
$parameters = $this->resolveClassMethodDependencies(
$route->parametersWithoutNulls(), $controller, $method
);

if (method_exists($controller, 'callAction')) {
return $controller->callAction($method, $parameters);
}

return $controller->{$method}(...array_values($parameters));
}
}

依赖注入解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?php

namespace Illuminate\Routing;

trait RouteDependencyResolverTrait
{
protected function resolveClassMethodDependencies(array $parameters, $instance, $method)
{
if (!method_exists($instance, $method)) {
return $parameters;
}

return $this->resolveMethodDependencies(
$parameters, new ReflectionMethod($instance, $method)
);
}

public function resolveMethodDependencies(array $parameters, ReflectionFunctionAbstract $reflector)
{
$instanceCount = 0;

$values = array_values($parameters);

foreach ($reflector->getParameters() as $key => $parameter) {
$instance = $this->transformDependency(
$parameter, $parameters
);

if (!is_null($instance)) {
$instanceCount++;

$this->spliceIntoParameters($parameters, $key, $instance);
} elseif (!isset($values[$key - $instanceCount]) &&
$parameter->isDefaultValueAvailable()) {
$this->spliceIntoParameters($parameters, $key, $parameter->getDefaultValue());
}
}

return $parameters;
}

protected function transformDependency(ReflectionParameter $parameter, $parameters)
{
$className = Reflector::getParameterClassName($parameter);

if ($className && !$this->alreadyInParameters($className, $parameters)) {
return $parameter->isDefaultValueAvailable()
? null
: $this->container->make($className);
}

return null;
}
}

响应处理

响应构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php

namespace Illuminate\Routing;

class Router
{
public function prepareResponse($request, $response)
{
return static::toResponse($request, $response);
}

public static function toResponse($request, $response)
{
if ($response instanceof Responsable) {
$response = $response->toResponse($request);
}

if ($response instanceof PsrResponseInterface) {
$response = (new HttpFoundationFactory)->createResponse($response);
} elseif ($response instanceof Model && $response->wasRecentlyCreated) {
$response = new JsonResponse($response, 201);
} elseif (!$response instanceof SymfonyResponse &&
($response instanceof Arrayable ||
$response instanceof Jsonable ||
$response instanceof ArrayObject ||
$response instanceof JsonSerializable ||
$response instanceof stdClass ||
is_array($response))) {
$response = new JsonResponse($response);
} elseif (!$response instanceof SymfonyResponse) {
$response = new Response($response, 200, ['Content-Type' => 'text/html']);
}

if ($response->getStatusCode() === Response::HTTP_NO_CONTENT) {
$response->setContent('');
}

return $response->prepare($request);
}
}

请求上下文

请求对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php

namespace Illuminate\Http;

class Request extends SymfonyRequest
{
protected $json;

protected $convertedFiles;

protected $userResolver;

protected $routeResolver;

public static function capture()
{
static::enableHttpMethodParameterOverride();

return static::createFromBase(SymfonyRequest::createFromGlobals());
}

public function user($guard = null)
{
return call_user_func($this->getUserResolver(), $guard);
}

public function route($param = null, $default = null)
{
$route = call_user_func($this->getRouteResolver());

if (is_null($route) || is_null($param)) {
return $route;
}

return $route->parameter($param, $default);
}

public function expectsJson()
{
return ($this->ajax() && !$this->pjax() && $this->acceptsAnyContentType()) ||
$this->wantsJson();
}

public function wantsJson()
{
$acceptable = $this->getAcceptableContentTypes();

return isset($acceptable[0]) &&
Str::contains(strtolower($acceptable[0]), ['/json', '+json']);
}
}

请求生命周期钩子

中间件终止

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php

namespace Illuminate\Foundation\Http;

class Kernel
{
public function terminate($request, $response)
{
$this->terminateMiddleware($request, $response);

$this->app->terminate();
}

protected function terminateMiddleware($request, $response)
{
$middlewares = $this->app->shouldSkipMiddleware() ? [] : array_merge(
$this->gatherRouteMiddleware($request),
$this->middleware
);

foreach ($middlewares as $middleware) {
if (!is_string($middleware)) {
continue;
}

$instance = $this->app->make($middleware);

if (method_exists($instance, 'terminate')) {
$instance->terminate($request, $response);
}
}
}
}

应用终止回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

namespace Illuminate\Foundation;

class Application
{
protected $terminatingCallbacks = [];

public function terminating($callback)
{
$this->terminatingCallbacks[] = $callback;

return $this;
}

public function terminate()
{
foreach ($this->terminatingCallbacks as $callback) {
$this->call($callback);
}
}
}

性能优化

中间件优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class OptimizeMiddleware
{
protected array $skipRoutes = [
'api/health',
'api/ping',
];

public function handle(Request $request, Closure $next)
{
if ($this->shouldSkip($request)) {
return $next($request);
}

// 执行中间件逻辑
return $next($request);
}

protected function shouldSkip(Request $request): bool
{
foreach ($this->skipRoutes as $route) {
if ($request->is($route)) {
return true;
}
}

return false;
}
}

请求缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;

class CacheResponse
{
public function handle(Request $request, Closure $next, int $ttl = 3600)
{
if (!$request->isMethod('GET')) {
return $next($request);
}

$key = $this->getCacheKey($request);

if (Cache::has($key)) {
return response(Cache::get($key))
->header('X-Cache', 'HIT');
}

$response = $next($request);

if ($response->status() === 200) {
Cache::put($key, $response->getContent(), $ttl);
$response->header('X-Cache', 'MISS');
}

return $response;
}

protected function getCacheKey(Request $request): string
{
return 'response:' . md5($request->fullUrl());
}
}

总结

Laravel 13 的请求处理流程包括:

  • 入口文件引导
  • HTTP Kernel 初始化
  • 全局中间件处理
  • 路由匹配与分发
  • 路由中间件管道
  • 控制器执行
  • 响应构建与返回
  • 终止回调执行

深入理解请求生命周期有助于优化应用性能和排查问题。