yii2自定义验证规则有三种方式:内联验证器(适合简单局部逻辑,如密码确认)、独立validator类(推荐复用场景,如身份证校验)、扩展核心验证器(微调现有行为,如严格required)。

Yii2 中自定义验证规则主要通过三种方式实现:在模型中定义 inline validator(内联验证器)、创建独立的 validator 类,或复用/扩展核心验证器。关键在于让验证逻辑可复用、易测试,并能正确返回错误信息。
在模型中使用 inline validator(适合简单、局部逻辑)
直接在 rules() 方法里写匿名函数或指向模型方法的字符串,适合一次性、业务耦合度高的校验,比如“密码和确认密码一致”或“手机号格式需匹配特定运营商号段”。
- 写法示例(方法名形式):
public function rules()
{
return [
['phone', 'validatePhonePrefix'],
['password_confirm', 'compare', 'compareAttribute' => 'password'],
];
}
public function validatePhonePrefix($attribute, $params)
{
$prefixes = ['139', '188', '156'];
$val = $this->$attribute;
if ($val && !in_array(substr($val, 0, 3), $prefixes)) {
$this->addError($attribute, '仅支持 139、188、156 开头的手机号');
}
}
- 注意:
addError()必须显式调用,否则不会触发错误;$attribute是当前字段名,$params可传额外参数(如['on' => 'register'])。
创建独立的 Validator 类(推荐用于复用场景)
继承 yiialidatorsValidator,重写 validateAttribute()(单字段)或 validateAttributes()(跨字段)。适用于邮箱白名单校验、身份证号算法验证、远程唯一性检查等。
- 步骤简明:
// @app/validators/IdCardValidator.php
namespace appalidators;
use yiialidatorsValidator;
class IdCardValidator extends Validator
{
public function validateAttribute($model, $attribute)
{
$id = $model->$attribute;
if (!preg_match('/^d{17}[dXx]$/', $id)) {
$this->addError($model, $attribute, '身份证格式不正确');
return;
}
// 这里可加入校验码逻辑(略)
if (!$this->isValidChecksum($id)) {
$this->addError($model, $attribute, '身份证校验码错误');
}
}
private function isValidChecksum($id)
{
// 实现 18 位身份证最后一位校验逻辑
return true; // 简化示意
}
}
- 在模型中使用:
['id_card', 'app\validators\IdCardValidator'] - 支持配置参数,例如:
['id_card', 'app\validators\IdCardValidator', 'strict' => true],并在init()或验证方法中读取$this->strict。
复用并扩展核心验证器(如增强 required 或 email)
有时只需微调已有行为,比如让 required 在特定场景下允许空格字符串视为无效,或让 email 支持中文域名(不推荐生产环境放宽,但可用于内部系统)。
- 继承并覆盖关键方法即可:
class StrictRequiredValidator extends yiialidatorsRequiredValidator
{
protected function validateValue($value)
{
if (is_string($value)) {
$value = trim($value);
}
return parent::validateValue($value);
}
}
- 使用时同普通 validator:
['name', 'app\validators\StrictRequiredValidator'] - 优势是保留原有配置项(
message、on、when等),无需重复实现。
注意事项与最佳实践
避免常见坑点,提升稳定性和可维护性:
- 验证器中不要做耗时操作(如远程 API 调用),如必须,应设超时、加缓存,并考虑异步或前端预检;
- 多字段联合验证优先用
validateAttributes(),避免在多个validateAttribute()中重复取值或判断; - 客户端验证(
clientValidate)可选配,返回 JS 字符串,用于生成前端 JS 校验逻辑(需开启enableClientValidation); - 国际化提示语统一走
Yii::t(),例如:$this->addError($model, $attribute, Yii::t('app', '手机号已注册'));; - 单元测试建议单独对 validator 类编写,不依赖模型实例,更易隔离验证逻辑。











