thinkphp 6 的 input() 支持自定义过滤器,需通过容器绑定实现;phonefilter 示例展示手机号标准化处理;过滤器仅支持单次调用、不可链式拼接,且须避免副作用操作。

ThinkPHP 6 的 input() 不支持自定义过滤器?
不是不支持,而是默认没暴露扩展入口。ThinkPHP 6 的 input() 底层走的是 think\helper\Str::filter() + 预设规则,但 filter 函数本身是静态私有方法,不能直接挂载新规则;真正可插拔的点在 think\Request 类的 filter 属性和 filterValue() 方法。
常见错误现象:input('name', '', 'htmlspecialchars') 能用,但想写 input('phone', '', 'PhoneFilter') 直接报错 —— 因为 PhoneFilter 没注册进过滤器容器。
- 必须手动把自定义类绑定到
think\contract\FilterInterface容器别名下(如'phone' => PhoneFilter::class) - 过滤器类必须实现
__invoke($value, $default = null, $args = [])方法 -
input()第三个参数传字符串时,会自动从容器里解析对应服务,否则 fallback 到 PHP 内置函数
如何注册一个手机号格式化过滤器(PhoneFilter)
ThinkPHP 6 的服务容器支持运行时绑定,最佳位置是 app/provider.php 或中间件初始化阶段。不要在控制器里临时 bind,否则每次请求都重复注册,且无法被 input() 自动识别。
使用场景:统一将前端传的 "138-1234-5678"、"+86 13812345678"、" 13812345678 " 标准化为纯 11 位数字。
- 新建
app/filter/PhoneFilter.php,实现__invoke:
namespace app\filter;
class PhoneFilter
{
public function __invoke($value, $default = null, $args = [])
{
if (empty($value)) return $default;
return preg_replace('/[^0-9]/', '', (string)$value);
}
}
- 在
app/provider.php中注册:
use think\Container;
use app\filter\PhoneFilter;
Container::getInstance()->bind('phone', PhoneFilter::class);
- 控制器中即可使用:
input('mobile', '', 'phone')
input() 过滤链执行顺序与参数穿透问题
ThinkPHP 的过滤器调用是单次执行,不支持像 Laravel 那样链式拼接(如 'trim|phone|intval')。第三个参数只接受一个过滤器标识,多个处理必须封装进单个过滤器内部。
容易踩的坑:input('price', 0, 'floatval|intval') 看似合理,实际只会尝试调用 floatval|intval 这个函数 —— 报 Call to undefined function floatval|intval() 错误。
- 正确做法:写一个组合过滤器,比如
PriceFilter,内部按需调用floatval→round→intval - 如果需要动态参数(如保留小数位数),通过
$args传入:input('price', 0, 'price:2'),然后在PriceFilter::__invoke()里用explode(':', $args[0] ?? '2')解析 - 注意:当
$value是数组时,filterValue()默认不会递归处理,需自行加 foreach
兼容性与性能影响:别在过滤器里做 DB 查询或远程调用
所有注册到 input() 过滤链里的逻辑,会在每次调用 input() 时同步执行。如果过滤器里查数据库、调 API、读大文件,会直接拖慢所有接口响应,且无法缓存。
性能影响明显的情况:在列表接口中对每条记录的 user_id 字段反复调用 input('user_id', '', 'UserValidator'),而该过滤器内部做了 UserModel::find() —— 这等于 N+1 查询。
- 验证类逻辑(如是否存在、是否合法)应放在业务层或验证器(
Validate)中,而非 input 过滤器 - 过滤器只做无副作用的数据变形:清洗、截断、编码转换、正则替换
- 如果必须关联查询,改用
think\Validate的rule+callback,它支持延迟执行和复用
最常被忽略的一点:过滤器返回值类型必须稳定。比如 PhoneFilter 对空字符串返回 '',但对 null 返回 null,下游代码若假设返回总是字符串,就会触发 Notice。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











