ThinkPHP 6.x模型字段校验统一用$rule,validate为5.x遗留;日期需显式指定格式如date|dateFormat:Y-m-d H:i:s,金额须存整数(分)、通过访问器转换,验证提示需手动配置message或语言包。

模型字段校验用 validate 还是 rule?
ThinkPHP 6.x 中,模型字段格式校验统一走 rule(即验证规则),validate 是旧版(5.x)遗留写法,新项目别混用。直接在模型类里定义 protected $rule = [],它会自动对接验证器逻辑。
常见错误:把日期校验写成 'create_time' => 'date',结果表单传字符串 "2024-10-05" 通过了,但传 "2024/10/05" 或 "2024-10-05 12:00" 就失败——因为内置 date 规则只认标准 Y-m-d 格式,不兼容时间部分或分隔符变体。
- 日期字段建议用
'create_time' => 'date|dateFormat:Y-m-d H:i:s'显式指定格式,比单纯date更可控 - 金额字段别用
number(它允许负数和科学计数法),改用float|between:0,99999999.99+ 自定义正则^([1-9]\d*\.?\d{0,2}|0\.\d{1,2})$ - 所有规则默认对空值放行;若字段必填,得额外加
require,比如'price' => 'require|float|between:0,99999999.99'
日期字段入库前自动标准化:用 setAttr 而不是靠验证器
验证器只负责“拦错”,不负责“转格式”。用户提交 "2024/10/05",验证通过后直接存进数据库,MySQL 可能报 Incorrect date value —— 因为它不认斜杠分隔符。
正确做法是在模型里加 setCreateTimeAttr 这类访问器,把输入统一转成 Y-m-d H:i:s 格式再赋值:
立即学习“PHP免费学习笔记(深入)”;
protected function setCreateTimeAttr($value)
{
if (empty($value)) return null;
// 兼容多种输入:时间戳、Y/m/d、Y-m-d H:i、Y-m-d H:i:s
return date('Y-m-d H:i:s', strtotime($value));
}
注意:别在访问器里做验证(如抛异常),否则和验证器逻辑重复;也别调用 Carbon::parse() 等重型对象,简单 strtotime + date 足够且快。
money 字段存整数还是小数?TP 模型怎么避免精度丢失
金额必须用整数(单位:分)存数据库,这是硬性要求。用 decimal(10,2) 存小数看似方便,但 PHP 浮点运算、MySQL 的 DECIMAL 在某些版本存在隐式截断风险,尤其涉及聚合计算时。
模型层要主动拦截并转换:
- 写入前:在
setPriceAttr里把元转成分,return round($value * 100); - 读取时:在
getPriceAttr里把分转回元,return $value / 100;(注意这里返回的是 float,前端展示需用number_format($price, 2)) - 搜索金额范围(如查 10~100 元)要同步换算:
where('price', 'between', [1000, 10000])
漏掉任何一环,都会导致查询不准或页面显示 99.99999999999999 这种怪数。
验证失败时提示中文不生效?检查 lang/zh-cn/validate.php 和 message
默认验证提示是英文(如 date format error),即使系统语言设为中文也不自动切换。原因:TP 验证器的提示语由语言包控制,但模型里的 $rule 不会自动加载语言变量。
两个解决路径:
- 在规则数组里显式写
message:'create_time' => ['date' => '日期格式不正确,请使用 YYYY-MM-DD'] - 或统一维护语言包:在
lang/zh-cn/validate.php补全键名,例如'date' => '日期格式不正确',然后模型中启用:protected $message = true;
容易被忽略的是:自定义正则(如金额正则)的提示必须手写 message,语言包不识别正则规则。



















