中间件是在请求到达应用核心逻辑之前或者响应返回给客户端之前执行的一段通用处理逻辑,常用于请求校验、权限判断、日志记录、跨域处理等场景,能有效避免重复代码,提升项目的可维护性。

中间件的核心作用
在Laravel中,中间件本质上是一个实现了handle方法的类,请求会按照中间件的注册顺序依次经过这些类的处理,处理完成后才会到达对应的控制器方法。如果我们想要实现用户登录状态校验,不需要在每个控制器方法里都写一遍校验逻辑,只需要把这个逻辑放到中间件里,然后把中间件绑定到对应的路由上就可以实现复用。
Laravel中自定义中间件的步骤
1. 创建中间件文件
Laravel提供了命令行工具可以快速创建中间件,我们只需要在项目根目录执行以下命令:
<?php
// 执行命令:php artisan make:middleware CheckLogin
// 生成的中间件文件默认在 app/Http/Middleware 目录下
namespace AppHttpMiddleware;
use Closure;
use IlluminateHttpRequest;
class CheckLogin
{
/**
* 处理传入的请求
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
// 这里编写具体的中间件逻辑
// 示例:校验用户是否登录
if (!$request->session()->has('user_id')) {
return redirect('/login');
}
// 校验通过,把请求传递给下一个中间件或者控制器
return $next($request);
}
}
2. 注册中间件
创建完中间件之后,需要把中间件注册到Laravel的中间件列表中,才能生效。如果是全局中间件,需要把中间件的类路径添加到app/Http/Kernel.php的$middleware数组中;如果是路由中间件,需要添加到$routeMiddleware数组中,并且给中间件起一个别名方便后续使用。
以下是注册路由中间件的示例:
<?php
// app/Http/Kernel.php 部分代码
namespace AppHttp;
use IlluminateFoundationHttpKernel as HttpKernel;
class Kernel extends HttpKernel
{
// 全局中间件,每个请求都会执行
protected $middleware = [
// ... 其他全局中间件
];
// 路由中间件,需要手动绑定到路由才会生效
protected $routeMiddleware = [
'auth' => AppHttpMiddlewareAuthenticate::class,
'guest' => AppHttpMiddlewareRedirectIfAuthenticated::class,
// 注册我们自定义的登录校验中间件,别名为check_login
'check_login' => AppHttpMiddlewareCheckLogin::class,
// ... 其他路由中间件
];
}
3. 使用自定义中间件
注册完成之后,就可以在路由定义的时候使用这个中间件了,支持单个路由绑定、路由组绑定两种方式。
单个路由绑定的示例:
<?php
// routes/web.php
use IlluminateSupportFacadesRoute;
// 只有登录的用户才能访问这个路由
Route::get('/user/profile', function () {
return view('profile');
})->middleware('check_login');
// 也可以使用完整类名绑定,不需要提前注册别名
Route::get('/user/order', function () {
return view('order');
})->middleware(AppHttpMiddlewareCheckLogin::class);
路由组绑定的示例,适合多个路由都需要同一个中间件的场景:
<?php
// routes/web.php
use IlluminateSupportFacadesRoute;
// 这个路由组里的所有路由都需要登录校验
Route::middleware(['check_login'])->group(function () {
Route::get('/user/info', function () {
return view('user_info');
});
Route::get('/user/setting', function () {
return view('user_setting');
});
});
中间件的进阶用法
前置中间件和后置中间件
上面的示例是前置中间件,也就是在请求到达控制器之前执行逻辑。如果需要在响应返回给客户端之前执行逻辑,可以定义后置中间件,后置中间件的handle方法需要接收$request和$next两个参数,先调用$next($request)得到响应,再对响应做处理。
<?php
namespace AppHttpMiddleware;
use Closure;
use IlluminateHttpRequest;
use IlluminateHttpResponse;
class LogRequest
{
public function handle(Request $request, Closure $next)
{
// 先执行下一个中间件或者控制器,得到响应
$response = $next($request);
// 后置逻辑:记录请求和响应的信息
// 这里可以写日志存储的逻辑
return $response;
}
}
中间件传参
如果中间件需要接收参数,可以在定义中间件的时候给handle方法增加额外的参数,使用的时候在路由绑定中间件的时候传递参数即可。
<?php
// 定义带参数的中间件
namespace AppHttpMiddleware;
use Closure;
use IlluminateHttpRequest;
class CheckRole
{
public function handle(Request $request, Closure $next, $role)
{
// 校验用户的角色是否匹配
if ($request->user()->role != $role) {
return abort(403, '无权限访问');
}
return $next($request);
}
}
// 路由中使用,传递参数admin
Route::get('/admin/dashboard', function () {
return view('admin_dashboard');
})->middleware('check_role:admin');
常见问题说明
如果中间件没有生效,首先可以检查是否在Kernel.php中正确注册了中间件,然后检查路由是否绑定了对应的中间件。如果中间件逻辑没有执行,可以在handle方法里打断点或者输出日志,排查是否进入了中间件方法。另外要注意中间件的执行顺序,全局中间件的执行顺序和$middleware数组中的顺序一致,路由中间件的执行顺序和绑定时候的顺序一致。
phpLaravel中间件middleware修改时间:2026-06-25 18:33:36