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 初始化
- 全局中间件处理
- 路由匹配与分发
- 路由中间件管道
- 控制器执行
- 响应构建与返回
- 终止回调执行
深入理解请求生命周期有助于优化应用性能和排查问题。