tp8验证器规则需严格满足执行前提:regex须带分隔符和u修饰符、反斜杠双写、禁用命名捕获组;unique排除id需外部传参且字段对齐;空值默认跳过regex,须加require;验证器须命令生成、路径命名空间类名三者一致,并默认启用strict模式。

TP5 的验证器规则语法在 TP8 中基本能跑通,但很多写法会静默失效或触发严格报错——不是“不兼容”,而是“被限制执行条件”。关键不在规则本身,而在你如何声明、如何调用、以及是否满足 TP8 的底层校验前提。
regex 规则必须带分隔符和 u 修饰符
TP5 写 ^1[3-9]d{9}$ 就能用,TP8 直接报 PcreException 或匹配失败。原因:TP8 要求正则字符串是完整可执行的 PCRE 模式,不能只给“表达式片段”。
- ✅ 正确:
'mobile' => '#^1[3-9]d{9}$#u'(推荐用#做分隔符,避免与 URL/email 冲突) - ❌ 错误:
'mobile' => '^1[3-9]d{9}$'(缺分隔符)、'mobile' => '/^1[3-9]d{9}$/'(斜杠易冲突)、'mobile' => '#^1[3-9]d{9}$#'(缺u,含中文/emoji 时错位) - 反斜杠要双写:
d必须写成\d(PHP 字符串转义) - 命名捕获组如
(?P<name>...)</name>在 strict 模式下直接抛异常,改用(...)数字组
unique 规则动态排除自身 ID 的写法变了
TP5 支持 'username' => 'unique:User,id,except,id_value' 这种链式写法,TP8 不再识别 except 关键字,必须显式传参且字段名对齐。
- TP5 写法(TP8 失效):
'username' => 'unique:User,id,except,123' - TP8 正确方式:在调用
check()时传入额外参数:$validate->check($data, ['id' => $userId]),并在规则中写成'username' => 'unique:User,username,id' - 注意字段顺序:
unique:table,column,exclude_field,第三个参数是“用于排除的字段名”,不是值;值由外部数组传入 - 若用
$this->validate($data, 'UserValidate.edit'),需确保$data里已含id字段,否则排除逻辑不触发
空值默认跳过 regex,require 必须显式声明
TP5 下 'mobile' => 'regex' 对 null 或空字符串也会执行正则,TP8 默认跳过——这导致“空手机号没报错”这类隐蔽问题。
- ❌ 错误写法:
'mobile' => 'regex'(空值直接绕过,不校验) - ✅ 正确写法:
'mobile' => 'require|regex'(require强制非空,才走到regex) - 若允许为空但又要校验格式(比如“填了就必须是手机号”),得拆成两个规则:
'mobile' => 'regexWhenNotEmpty'—— 但 TP8 没这个内置规则,需自定义函数或用闭包 - 更稳妥做法:前端控住必填逻辑,后端只做“有值即校验”,用
require|regex覆盖绝大多数场景
验证器类生成和加载路径不能手写
TP5 可以随便建 app/validate/User.php,TP8 要求文件路径、命名空间、类名三者完全对齐,否则 Class not found 或规则不加载。
- 必须用命令生成:
php think make:validate UserValidate(生成到app/validate/UserValidate.php) - 首行必须加:
declare(strict_types=1);,否则类型校验失效 - 类名必须是
UserValidate,命名空间必须是appalidate,继承thinkValidate - 别把验证器放
appcommonalidate或apppialidate—— TP8 默认只扫描app/validate
最易被忽略的是:TP8 验证器默认启用 strict 模式,所有未声明的字段、未定义的规则、不合法的正则结构,都不会静默忽略,而是直接中断或报错。这不是 bug,是设计使然——它逼你把数据契约写清楚,而不是靠“大概能过”混过去。











