yii2参数验证需区分校验与清洗:内联验证器用于简单字段规则,独立验证类复用复杂逻辑,filter验证器预处理数据,api场景应前置统一拦截非法参数。

Yii2 中自定义参数验证、过滤非法值,核心在于区分“校验”和“清洗”两个动作:校验用于判断是否合法并报错,清洗用于修正或标准化输入。不能只靠 rules() 做兜底,尤其在 API 场景下,需主动拦截、统一处理。
用内联验证器做字段级合法性校验
适合逻辑简单、仅限当前模型使用的规则,比如密码一致性、枚举值限制、条件必填等。
- 写法必须是匿名函数或
[$this, 'methodName']数组形式,不能只写字符串名 - 方法签名固定为
function ($model, $attribute, $params),三个参数不可少 - 失败时调用
$model->addError($attribute, $message),不要 return false 或 throw - 若字段允许为空(没加 required),默认仍会执行验证;如需跳过空值,手动加判断:
if (empty($model->$attribute)) return; - 想让验证始终触发(哪怕字段为空或前面已出错),加上
'skipOnEmpty' => false, 'skipOnError' => false
用独立验证类复用复杂校验逻辑
适合手机号、身份证、URL 格式、敏感词过滤等可跨模型复用的场景。
- 新建类继承
yii\validators\Validator,类名必须以Validator结尾(如IDCardValidator) - 重写
validateAttribute()方法,内部调用$this->addError() - 在
init()中调用parent::init(),否则$this->message等属性不生效 - 参数通过 public 属性声明(如
public $strict = true;),在 rules 中传入:['id_card', 'IDCardValidator', 'strict' => false] - 如需支持前端 JS 校验,实现
clientValidateAttribute()并返回合法 JS 字符串
用 filter 验证器做参数清洗与预处理
不是用来报错,而是把脏数据变干净,比如去空格、转小写、HTML 过滤、null 转空字符串等。
-
['username', 'filter', 'filter' => 'trim']最常用,自动去除首尾空格 -
['content', 'filter', 'filter' => function ($value) { return \yii\helpers\HtmlPurifier::process($value); }]过滤 HTML 标签 -
['status', 'default', 'value' => self::STATUS_ACTIVE]设置默认值,当字段为空或未提交时生效 - 注意:filter 在 validate() 阶段就执行,早于其他验证规则,所以清洗后的值才参与后续校验
API 场景下统一拦截非法参数(推荐)
对于纯接口项目,不能依赖每个模型自己写 rules,应前置拦截,避免无效请求进入业务层。
- 创建 ActionFilter(如
ParamValidatorFilter),在 beforeAction 中统一读取 GET/POST 参数 - 按 action 配置规则数组,支持 required、type、pattern、in、min/max 等校验维度
- 校验失败直接抛
BadRequestHttpException,返回结构化错误 JSON - 配合
$strict = true可强制拒绝未声明的参数,防字段注入 - 比模型层 rules 更早介入,减少资源浪费,也更利于日志追踪和监控











