yii3支持原生psr-15中间件,配置通过$app->use()或路由级withmiddleware()实现,执行时机在路由解析后、控制器前,取代yii2中依赖behaviors和事件的伪中间件模式。

Yii3 支持原生 PSR-15 中间件,配置方式和执行机制与 Yii2.0 有根本性区别——Yii2.0 没有中间件概念,只能靠 behaviors 和事件模拟;Yii3 则把中间件作为请求生命周期的一等公民,可链式注册、分层拦截、统一调度。
Yii3 中间件配置方式
Yii3 使用 PSR-15 兼容的中间件接口,需实现 MiddlewareInterface::process() 方法。配置在应用启动时通过 $app->use() 或容器绑定完成:
- 全局中间件直接链式调用:
$app->use(new AuthMiddleware());<br>$app->use(new LoggingMiddleware());
- 路由级中间件可绑定到具体 handler:
$app->get('/api/user', [UserController::class, 'index'])<br> ->withMiddleware(AdminOnlyMiddleware::class); - 中间件类必须声明构造参数类型(依赖自动注入),例如:
public function __construct(private UserService $userService) {} - 不再需要手动触发
isValid = false或重写beforeAction(),直接return new Response(...)或调用$next->handle($request)即可控制流程
Yii2.0 根本没有中间件,只有行为模拟
Yii2.0 的 behaviors() 返回的是行为配置数组,不是中间件实例。它依赖控制器生命周期事件(如 EVENT_BEFORE_ACTION)做钩子,本质是“伪中间件”:
- 不能跨控制器复用逻辑而不侵入控制器代码——每个控制器都要声明
public $behaviors = [...] - 无法在路由匹配前执行(比如校验域名、解析 JWT 头),因为行为只在控制器初始化后才挂载
- 没有标准接口,类名、方法名、参数约定全靠开发者约定,容易写出不可测、难调试的逻辑
- 常见错误是把权限检查写在
init()或beforeAction()里,导致无法动态开关或按 action 精确控制
关键差异:执行时机与作用域
Yii3 中间件运行在 路由解析之后、控制器执行之前,且可对任意 HTTP 请求生效(包括非 Web 应用,如 console 命令也可配中间件)。Yii2.0 的行为只能作用于 Web 控制器,且必须经过 Controller::runAction() 流程:
- Yii3 可在中间件中终止请求并返回 JSON 错误,不进入任何控制器
- Yii2.0 若想提前退出,必须在
beforeAction()中return false,但此时已创建控制器实例,资源开销更大 - Yii3 支持中间件组(middleware group)、条件启用(如仅开发环境加载 DebugToolbarMiddleware)
- Yii2.0 没有中间件组概念,所有逻辑都挤在 behaviors 数组或父类方法里,维护成本高
迁移建议:从 Yii2 行为升级到 Yii3 中间件
已有 Yii2 的 AccessControl、CorsFilter、LogBehavior 等,可对应转为独立中间件类:
- 将
AccessControl::rules配置移到中间件构造函数或容器参数中 - 把
beforeAction()中的 token 解析、用户认证逻辑提取为AuthMiddleware,返回UnauthorizedResponse终止流程 - 日志记录行为 →
RequestLoggingMiddleware,利用 PSR-3 Logger 接口注入 - 避免在中间件中访问
Yii::$app—— Yii3 已弃用 ServiceLocator,全部走 DI 容器注入











