可通过定义activequerybehavior类并挂载到自定义activequery中,实现按状态和时间范围的动态条件组装,避免重复代码;需正确声明事件、调用parent::init()、使用andfilterwhere防止无效sql。

当你在多个模型中反复写相似的查询逻辑(比如按状态筛选+时间范围过滤+关联预加载),又不想复制粘贴出一堆重复代码时,就需要把这部分行为抽成可复用的扩展模块。
定义通用查询行为类
在models/behaviors目录下新建ActiveQueryBehavior.php文件。
类必须继承\yii\base\Behavior,并在events()方法中声明要挂载的事件——这里只响应ActiveQuery::EVENT_BEFORE_BUILD,确保在SQL生成前介入。
这一步不能漏掉use yii\db\ActiveQuery;,否则EVENT_BEFORE_BUILD常量无法识别,运行时直接报错。
在ActiveQuery中注入行为
为需要复用逻辑的模型创建专属ActiveQuery类,例如UserQuery extends ActiveQuery。
在init()方法里调用$this->attachBehavior('commonFilter', ActiveQueryBehavior::class);。
【必须调用parent::init()】否则ActiveQuery内部初始化流程中断,后续where()、orderBy()等链式调用会失效。
实现动态条件组装
回到ActiveQueryBehavior类,在beforeBuild()方法中处理参数:
第一步:从Yii::$app->request->get()提取status和date_from参数;
第二步:若status存在且不为空,调用$this->owner->andFilterWhere(['status' => $status]);
第三步:若date_from为合法日期格式,追加$this->owner->andFilterWhere(['>=', 'created_at', $dateFrom]);
注意:必须用andFilterWhere()而非andWhere(),否则传入空字符串或null时会生成WHERE status = ''这种无效条件,导致查询结果为空。
挂载到具体模型
打开User.php模型文件,在find()静态方法中返回自定义Query类:
public static function find() {
return new UserQuery(get_called_class());
}
现在所有调用andFilterWhere。











