PHP框架中的中间件是请求处理流程里的重要组件,它可以在请求进入业务逻辑前或者响应返回前插入自定义处理逻辑,避免把非业务相关的代码耦合到控制器中,让代码结构更清晰,可维护性更高。

PHP框架中间件的核心作用
中间件的核心价值在于对请求和响应进行统一拦截处理,常见的作用可以分为以下几类:
- 身份验证与权限校验:比如检查用户是否登录、是否拥有访问当前接口的权限,未通过校验直接返回错误响应,不需要每个控制器都重复写校验逻辑。
- 请求预处理:比如校验请求参数的格式、过滤非法输入、转换请求参数的类型,确保进入控制器的参数是符合预期的。
- 日志记录与统计:记录请求的访问时间、IP地址、请求路径等信息,或者统计接口的调用次数,方便后续排查问题和分析业务数据。
- 响应后处理:比如在响应返回前统一添加响应头、格式化响应数据的结构,处理跨域相关的配置等。
新手如何定义中间件
不同PHP框架的中间件定义规则略有差异,这里以使用范围较广的Laravel框架为例,演示中间件的定义步骤。
1. 创建中间件文件
可以通过框架提供的命令行工具生成中间件模板,也可以手动创建中间件类。手动创建时,中间件类需要实现框架规定的方法,通常包含一个处理请求的核心方法。
<?php
namespace AppHttpMiddleware;
use Closure;
use IlluminateHttpRequest;
class CheckLogin
{
/**
* 处理传入的请求
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
// 检查用户是否登录,假设通过session判断
if (!$request->session()->has('user_id')) {
// 未登录返回错误响应
return response()->json(['code' => 401, 'msg' => '请先登录'], 401);
}
// 校验通过,继续执行下一个中间件或进入控制器
return $next($request);
}
}
2. 中间件的核心逻辑说明
上述示例是一个简单的登录校验中间件,核心逻辑在handle方法中实现:
- 第一个参数是当前的请求对象,可以从中获取请求参数、请求头、session等信息。
- 第二个参数是闭包函数,调用
$next($request)会把请求传递到下一个中间件,如果当前中间件不需要拦截请求,就必须调用这个方法,否则请求会终止在当前中间件。 - 如果需要在响应返回前做处理,可以在中间件中定义
terminate方法,框架会在响应发送给客户端后调用这个方法。
<?php
namespace AppHttpMiddleware;
use Closure;
use IlluminateHttpRequest;
use IlluminateHttpResponse;
class LogRequest
{
public function handle(Request $request, Closure $next)
{
// 请求处理逻辑
return $next($request);
}
/**
* 响应返回后的处理逻辑
*
* @param Request $request
* @param Response $response
* @return void
*/
public function terminate(Request $request, Response $response)
{
// 记录请求日志
file_put_contents(
storage_path('logs/request.log'),
date('Y-m-d H:i:s') . ' ' . $request->path() . PHP_EOL,
FILE_APPEND
);
}
}
新手如何注册中间件
定义好中间件之后,需要把中间件注册到框架中,才能让框架在请求处理流程中调用到它。注册方式也分为全局注册和路由分组注册两种。
1. 全局注册中间件
全局注册的中间件会对所有的请求生效,适合需要全局生效的逻辑,比如跨域处理、请求日志等。在Laravel中,全局中间件需要配置到app/Http/Kernel.php文件的$middleware数组中。
<?php
namespace AppHttp;
use IlluminateFoundationHttpKernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* 全局中间件列表,对所有请求生效
*
* @var array
*/
protected $middleware = [
// 其他默认全局中间件
AppHttpMiddlewareLogRequest::class,
];
// 其他配置项省略
}
2. 路由分组注册中间件
如果中间件只需要对部分路由生效,可以把中间件注册到路由分组中,或者单个路由上。首先需要给中间件起一个别名,配置到app/Http/Kernel.php的$routeMiddleware数组中。
<?php
namespace AppHttp;
use IlluminateFoundationHttpKernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* 路由中间件别名,用于路由中指定中间件
*
* @var array
*/
protected $routeMiddleware = [
// 其他默认路由中间件
'check_login' => AppHttpMiddlewareCheckLogin::class,
];
// 其他配置项省略
}
配置好别名之后,就可以在路由定义中使用这个中间件了:
<?php
use IlluminateSupportFacadesRoute;
// 单个路由使用中间件
Route::get('/user/info', function () {
return response()->json(['code' => 200, 'data' => ['name' => 'test']]);
})->middleware('check_login');
// 路由分组使用中间件,分组内所有路由都会生效
Route::middleware(['check_login'])->group(function () {
Route::get('/order/list', function () {
return response()->json(['code' => 200, 'data' => []]);
});
Route::post('/order/create', function () {
return response()->json(['code' => 200, 'msg' => '创建成功']);
});
});
中间件的使用注意事项
- 中间件的执行顺序和注册的顺序一致,全局中间件的执行顺序按照
$middleware数组的排列顺序,路由中间件的执行顺序按照middleware方法中传入的数组顺序。 - 不要在中间件中写过于复杂的业务逻辑,避免中间件执行时间过长影响请求响应速度。
- 如果中间件需要依赖注入其他服务,可以在中间件的构造函数中声明,框架会自动解析依赖。
PHPmiddlewareLaravel路由拦截请求处理修改时间:2026-06-20 08:06:24