tp6接口参数类型校验必须使用验证器类或反射注解,禁用手动if或裸数组;验证器需继承think\validate并显式声明规则,反射注解适用于轻量接口但不推荐强一致性场景。

TP6 接口参数类型校验不能靠手动 if 判断,也不能用裸数组规则硬塞,必须走验证器类或反射注解两条正路。核心是让校验逻辑可复用、可维护、不绕过,并且能准确识别 string/int/bool 等类型边界。
用验证器类做类型校验(推荐主用)
验证器是 TP6 官方支持的标准化方式,字段名与数据键必须严格一致,类型规则需显式声明:
- 继承 think\Validate,不能只写数组规则;例如
['email' => 'email']直接传给 validate() 会静默失效 - 基础类型规则直接使用内置标识:
'age' => 'number|between:18,120'、'status' => 'in:0,1,2'、'is_vip' => 'boolean' - 字符串类型注意空值陷阱:
'name' => 'require|alphaNum|min:1'比单纯require更严,因原生 require 不拦截空格或空字符串 - 日期/时间字段用
date或datetime规则,配合 format 参数如'create_time' => 'date:Y-m-d H:i:s' - 需自定义类型逻辑(如手机号、身份证号),写 public 方法,签名必须为
public function ruleMobile($value, $rule, $data, $field),返回布尔值
用反射+注解做动态类型校验(适合轻量接口)
不依赖验证器类文件,直接在控制器方法注释中声明规则,通过反射提取并执行校验:
- 在方法 DocBlock 中写明类型与约束,例如:
@param int $uid 必填|最小值:1、@param string $token 可选|长度:32 - 用 ReflectionMethod 读取参数名和注释,正则匹配提取规则,构建成校验配置数组
- 对每个参数执行类型强制转换(如
(int)$value)再比对,避免字符串 "123" 被当成 int 误放行 - 注意 null 默认值处理:若参数声明为
$age = null,但注释写“必填”,则需在校验时忽略默认值,只看实际传入值 - 该方式适合快速迭代的小型 API,但不建议用于金融、订单等强一致性场景
关键细节不能漏
无论哪种方式,以下三点直接影响类型校验是否真正生效:
-
输入源统一:不要混用
$request->param()、$request->post()、$request->get(),否则 JSON 请求体或带 query 的 POST 容易漏参;推荐先用$request->getInput()+ 内容类型判断解析,再合并 GET 和 body -
编码与空格归一化:中文参数未 UTF-8 编码、前后含不可见空格,会导致
is_numeric()或filter_var($v, FILTER_VALIDATE_INT)失败;建议在验证前统一trim()和mb_convert_encoding($v, 'UTF-8') -
错误信息聚合反馈:启用
batch(true),一次返回所有字段错误,而不是只报第一个;错误提示里避免暴露类型细节(如不说“期望 int,得到 string”),防止被用于探测接口结构











