yii2过滤器是基于事件的单向监听机制,非laravel式中间件链;其本质为继承actionfilter的行为类,通过监听event_before_action/after_action事件执行beforeaction(可中断)和afteraction(不可中断),多个过滤器按声明顺序同序执行前后逻辑。

Yii2 没有 Laravel 那种标准的中间件链(middleware pipeline),它的“过滤器”不是靠 $next($request) 逐层传递,而是基于控制器生命周期事件触发的、**单向监听式执行**。理解这点,才能避免照搬 Laravel 写法导致静默失效。
Filter 的本质是 ActionFilter 行为
Yii2 的过滤器(如 AccessControl、VerbFilter)都继承自 \yii\base\ActionFilter,它本身是一个 Behavior(行为),被挂载到控制器上,监听 EVENT_BEFORE_ACTION 和 EVENT_AFTER_ACTION 两个事件。
- 不是“链”,没有
$next回调;而是“钩子”,框架在动作执行前后自动触发对应方法 -
beforeAction()返回false会中断动作执行,返回true才继续——这是唯一“拦截”方式 -
afterAction()无法阻止动作执行,只能处理结果或修改响应 - 多个过滤器按声明顺序依次执行
beforeAction,再按**相同顺序**执行afterAction(不是逆序)
FilterChain 是历史遗留概念,已不推荐直接使用
早期 Yii2 版本(如 2.0.0–2.0.6)支持手动定义 filterAccessControl() 方法并调用 $filterChain->run(),但该机制已被弃用:
-
CFilterChain类属于旧版抽象,现代项目中基本见不到 - 当前官方文档和核心组件(如
AccessControl)全部走 Behavior + Event 模式 - 若在控制器里写
public function filters()返回数组,底层仍会自动包装成 Behavior 实例
所谓“链式调用”其实是错觉
有人看到多个过滤器生效,误以为是链式调用,实际是:
- 框架初始化控制器时,把所有声明的 Filter 注册为 Behavior
- 请求进入后,逐一调用每个 Behavior 的
beforeAction(),任一返回false就终止流程 - 动作执行完,再逐一调用每个 Behavior 的
afterAction(),顺序与 before 一致 - 不存在跨过滤器的数据透传(如 Laravel 中
$request->attributes可被下个中间件读取)
想模拟链式?得自己封装逻辑
如果真需要类似 Laravel 的 $next 流程(比如记录耗时、动态改请求参数),可行做法是:
- 写一个自定义 Behavior,在
beforeAction中修改$action->controller->view或设置全局状态(如Yii::$app->params['filter_context']) - 用事件代替:在
EVENT_BEFORE_ACTION发送自定义事件,其他模块监听并处理,再由主逻辑决定是否继续 - 避免在
web/index.php层硬编码中间件类——Yii2 不识别['middleware' => [...]]这类配置,会直接忽略











