中间件类无需继承任何类,只需实现handle方法并调用$next($request);注册分全局、分组、单路由三层;参数通过逗号分隔传入handle第三及后续参数。

中间件类必须继承 IlluminateBusMiddlewaredispatchable 吗?
完全不需要。这是常见误解——Dispatchable 是用于命令总线(Bus)的 trait,和中间件无关。laravel 中间件本质就是一个带 handle() 方法的普通 php 类,只要它接受 $request 和 $next 两个参数,并最终调用 $next($request) 即可。
正确基类是空的,无需继承任何类(当然你也可以选择继承 IlluminatehttpMiddlewareTrustProxies 这类已有的中间件基类,但非常少见)。官方推荐写法就是:
class CheckAge { public function handle($request, Closure $next) { if ($request->age < 20) { return redirect('home'); } return $next($request); } }
如何注册中间件:全局、分组、单路由三者怎么选?
注册位置决定作用范围,选错会导致中间件不生效或过度执行。
- 全局中间件:在
app/Http/Kernel.php的$middleware数组里,对所有 HTTP 请求生效(包括 API 和 Web),适合日志、CORS、请求解析等基础设施层逻辑 - 分组中间件:在
$middlewareGroups里,比如web或api。路由用Route::middleware(['web'])或直接用Route::group(['middleware' => ['web']], ...)调用。注意:Laravel 默认给routes/web.php自动套了web组,所以你在里面写的路由默认已有 session、csrf 等中间件 - 单路由中间件:最细粒度控制,直接链式调用
->middleware(CheckAge::class)。适合权限校验、数据预加载等业务强相关逻辑
别把需要鉴权的 CheckAge 放进 $middleware 全局数组——它会在每次请求(包括静态资源、健康检查接口)里执行,浪费性能且可能报错。
handle() 方法里忘记调用 $next($request) 会怎样?
请求会在这里「卡住」,既不向下传递,也不返回响应,最终超时或抛出 IlluminateRoutingExceptionsInvalidSignatureException(如果用了签名中间件)之类难以定位的异常。更常见的是浏览器一直转圈、API 返回空响应、nginx 报 504 gateway Timeout。
务必确保每个分支都返回值:
public function handle($request, Closure $next) { if ($request->user() && $request->user()->banned) { return response('Banned!', 403); // ✅ 返回响应 } if ($request->expectsjson()) { return $next($request); // ✅ 继续执行 } return redirect('/login'); // ✅ 显式返回 }
不要写 if (...) { return ...; } 然后后面没 return —— PHP 不会自动补全,这属于硬性逻辑错误。
中间件参数怎么传?check:role,admin 是怎么解析的?
路由定义中写的 ->middleware('check:role,admin'),Laravel 会把 role,admin 当作字符串传给中间件的 handle() 第三个参数(需手动声明):
public function handle($request, Closure $next, $type, $value) { // $type = 'role', $value = 'admin' if ($type === 'role') { if (!$request->user() || !$request->user()->hasRole($value)) { abort(403); } } return $next($request); }
注意:$type 和 $value 的顺序必须和 : 后逗号分隔的顺序一致,且参数个数要匹配。多于或少于都会报 Too few arguments to function 错误。没有参数就别写冒号,写成 ->middleware(CheckAge::class) 即可。
参数只支持字符串,不能传数组或对象;复杂逻辑建议改用请求属性或 session 存储,而非塞进中间件参数里。