ThinkPHP 6 的 validate 方法仅校验不自动过滤参数,需显式配置 filter 或手动处理;input() 与 Request::param() 均不默认转义,filter 不作用于嵌套字段,验证器中 filter 仅在实例化调用 check() 时生效,且不修改原始数据。

ThinkPHP 6 的 validate 方法默认不自动过滤参数
很多人以为调用 validate 就能同时校验+清洗,其实它只做校验,filter、htmlspecialchars 这类操作不会自动发生。参数原样进控制器,你得自己动手“刮一层”。
常见错误现象:input('post.content') 拿到带 <script></script> 的字符串,校验通过了,但没转义就直接 echo 到页面,XSS 就来了。
- 必须显式调用
filter参数,比如input('post.content', '', 'htmlspecialchars') - 或在验证规则里加
filter键:['filter' => 'htmlspecialchars'],但注意:这仅对验证器中定义的字段生效,且 TP6 验证器默认不触发 filter(需配合scene或手动调用data()+filter()) - 别依赖
input()的第三个参数做全局过滤——它只作用于当前字段,漏掉一个就少刮一块
TP6 中 Request::param() 和 input() 的过滤行为差异
Request::param() 是“懒人入口”,但它默认不做任何过滤;input() 更灵活,但容易误以为加了规则就等于清洗了。
使用场景:你写了个通用表单接收方法,想统一处理所有字符串字段。
立即学习“PHP免费学习笔记(深入)”;
-
Request::param()返回的是原始数据,连空格都不会 trim,input('name')也一样 - 要批量 trim + htmlspecialchars,得自己封装:
array_map(fn($v) => is_string($v) ? htmlspecialchars(trim($v)) : $v, request()->param()) - TP6 的
input()支持default和filter,但 filter 不支持数组嵌套字段(如input('user.name')加 filter 会失效) - 性能影响:每次调用
htmlspecialchars都有开销,高频接口建议只对展示用字段做,非必要字段(如 ID、状态码)跳过
验证器里写 filter 规则却没生效?检查这三点
验证器里写了 'content|内容' => 'require|filter:htmlspecialchars',但打印出来还是没转义——大概率是调用方式不对。
错误典型:直接 $this->validate($data, MyValidate::class),这个静态调用不走验证器实例的 filter 流程。
- 必须 new 验证器实例并调用
check():(new MyValidate())->check($data) - 或者用
validate()->rule(MyValidate::class)->check($data)(TP6.1+) - 验证器里的
filter只在check()执行时生效,且只修改验证器内部使用的数据副本,原$data不变 - 兼容性注意:TP6.0.9 之前,
filter规则不支持闭包函数,只能用内置函数名或字符串表达式
用中间件统一过滤请求参数,但别碰 file 和 json 类型
想一劳永逸?写个中间件遍历 request()->param() 做 htmlspecialchars,听起来干净,实则埋雷。
使用场景:后台管理系统的普通表单提交(application/x-www-form-urlencoded)
- 绕过文件字段:
if (is_object($value) && method_exists($value, 'isValid')) continue;(判断是否为UploadedFile) - 跳过 JSON 请求体:
if (request()->header('content-type') === 'application/json') break;,否则把 JSON 字符串双转义 - 不要对数字、布尔、数组字段硬套
htmlspecialchars,会破坏类型,TP6 的input()本身已做类型转换,乱 filter 可能导致int变成string - 中间件顺序很重要:必须在路由和控制器之前,但要在
SessionMiddleware之后(否则 session 数据可能被误过滤)
最麻烦的地方不是怎么写过滤逻辑,而是得时刻记住:哪些字段是给前端渲染的、哪些是进数据库的、哪些是当条件查数据的——同一份参数,在不同环节需要不同的“刮法”。漏判一个用途,就可能刮错地方。



















