Yii2模型校验必须在rules()方法返回二维数组,字段名须与属性名严格一致;内置验证器如required、email需正确拼写;条件验证用when回调并处理未定义属性;自定义验证须调用addError()。

在Yii2中为模型添加数据校验逻辑,必须在模型类的rules()方法里返回一个二维数组,每条规则控制一个或多个字段的验证行为,漏写、格式错或参数名拼错都会导致验证静默失效。
基础规则写法与结构
打开模型文件,在rules()方法内按固定格式书写规则数组:每个子数组代表一条规则,第一个元素是字段名(字符串)或字段名数组(多个字段共用同一条规则),第二个元素是验证器名称(如'required'、'email'),后续键值对是该验证器的配置项。
例如,要求username和email都必填,且email格式合法:[['username', 'email'], 'required']→['email', 'email']。
注意:字段名必须与模型属性名完全一致,大小写敏感;若字段不存在于模型定义中,验证会跳过且无提示。
常用内置验证器速查
直接使用框架内置验证器无需额外代码,只需在规则中指定名称和必要参数:
方法一:必填校验 → ['title', 'required'],空字符串、null、未提交均触发错误。
方法二:邮箱格式 → ['email', 'email', 'enableIDN' => true],开启国际化域名支持时需显式启用。
方法三:数值范围 → ['age', 'integer', 'min' => 0, 'max' => 150],注意integer不接受浮点数,number才支持小数。
方法四:唯一性检查 → ['username', 'unique', 'targetClass' => User::class, 'message' => '用户名已被注册'],【targetClass必须指向真实存在的AR类】,否则抛出类未找到异常。
条件验证:when与skipOnEmpty配合
当某个字段是否需要验证取决于其他字段取值时,必须用when回调函数动态控制,不能靠前端隐藏字段来规避。
第一步:定义规则并传入when参数['phone', 'required', 'when' => function ($model) { return $model->country === 'CN'; }]
第二步:确认skipOnEmpty行为
默认情况下,即使when返回true,若phone为空,仍会跳过验证;若业务要求“中国用户必须填手机号,哪怕填了空字符串也算违规”,则追加'skipOnEmpty' => false。
第三步:避免when内部访问未定义属性 → 若$model->country未声明或未赋值,回调会报Notice: Trying to get property of non-object;应在回调开头加判断:if (!isset($model->country)) return false;
自定义内联验证器
适合只在当前模型用一次、逻辑较轻的校验,比如密码与确认密码比对。
在rules()中写匿名函数:['password_repeat', function ($model, $attribute, $params) { if ($model->password !== $model->$attribute) { $model->addError($attribute, '两次输入的密码不一致'); } }]
函数签名三个参数缺一不可:$model是当前模型实例,$attribute是当前被验证字段名(这里是password_repeat),$params是规则中传入的额外参数数组(本例未用)。
验证失败必须调用$model->addError($attribute, $message),【不能用return false或throw new Exception】,否则框架捕获不到错误,表单提交成功却数据异常。
独立验证类写法
适合复用性强、逻辑复杂或需配置参数的场景,例如校验11位手机号并区分运营商。
新建文件@app/validators/PhoneValidator.php,内容如下:namespace appalidators;use yiialidatorsValidator;class PhoneValidator extends Validator { public $strict = true; public function init() { parent::init(); if ($this->message === null) { $this->message = '手机号格式不正确。'; } } public function validateAttribute($model, $attribute) { $value = $model->$attribute; if ($this->strict && !preg_match('/^1[3-9]d{9}$/', $value)) { $model->addError($attribute, $this->message); } } }
类名必须以Validator结尾,否则自动加载失败;init()中必须调用parent::init(),否则$this->message等父类属性为null。
在模型rules()中使用:['mobile', 'app\validators\PhoneValidator', 'strict' => true],命名空间路径用双反斜杠转义。


















