yii2校验浮点型需自定义规则——内置number/double仅检类型,无法控精度、范围及格式;应拆分格式(正则)与数值(float转换后比较)校验,并用skiponempty控制触发时机。

Yii2 中校验浮点型参数不能只靠 number 或 double 内置规则——它们仅检查类型,不控制精度、范围或格式(比如是否允许科学计数法、小数位数是否超限)。真实业务中常需「保留最多两位小数」「必须大于 0」「禁止整数形式输入」等约束,这时就得自定义规则。
用内联验证器控制小数位数和取值范围
适合单模型、一次性使用,比如商品价格字段 price 要求「大于 0,且最多两位小数」:
- 在
rules()中直接写匿名函数,签名必须为function ($model, $attribute, $params) - 先手动过滤空值(避免空字符串或 null 触发校验):
if ($model->$attribute === null || $model->$attribute === '') return; - 用正则判断格式:
if (!preg_match('/^\d+(\.\d{1,2})?$/', (string)$model->$attribute))确保是数字+可选的小数点+1~2位数字 - 再转成 float 做数值判断:
$val = (float)$model->$attribute; if ($val ,失败时调用 <code>$model->addError($attribute, '价格必须大于 0 且最多两位小数')
用独立验证类复用高精度校验逻辑
当多个模型都要校验「金额」「利率」「权重」等浮点字段,且要求统一精度策略(如四舍五入后比对、支持千分位兼容),建议抽成类:
- 新建
PriceValidator.php,类名必须以Validator结尾,继承yii\validators\Validator - 声明配置属性:
public $maxDecimal = 2; public $minValue = 0.01; - 在
init()中调用parent::init(),否则$this->message不可用 - 重写
validateAttribute($model, $attribute):提取数值、检查小数位、比较范围,出错调用$this->addError($model, $attribute, $this->message) - 在 rules 中使用:
['price', 'PriceValidator', 'maxDecimal' => 2, 'minValue' => 0.01]
绕过内置规则限制的常见技巧
number 规则默认允许整数、负数、科学计数法(如 1e5),但业务往往要禁用这些:
- 不要单独用
['price', 'number'],它无法拦截"123"(无小数点)或"-1.5" - 若需强制带小数点,正则应写为
/^\d+\.\d{1,2}$/(去掉?) - 若字段允许为空,但又想在非空时才校验浮点格式,务必加
'skipOnEmpty' => true到规则项里,否则空值也会进验证逻辑 - 客户端验证暂不支持,提交前仍需 JS 补充校验;如需实时提示,得配合 ActiveForm 的
enableAjaxValidation
不复杂但容易忽略细节,关键是把「格式校验」和「数值校验」拆开做,再结合 skipOnEmpty 控制触发时机。











