filter_var()清洗字符串需选对FILTER_SANITIZE_*类型:FILTER_SANITIZE_SPECIAL_CHARS转义HTML标签,FILTER_SANITIZE_FULL_SPECIAL_CHARS额外转义引号;PHP 8.1+已移除FILTER_SANITIZE_STRING;数字和邮箱须先清洗再严格校验;多维数组需递归处理;清洗后注意UTF-8编码与字段长度匹配。

PHP怎么用 filter_var() 清洗用户输入的字符串
直接用 filter_var() 最省事,但很多人传错 FILTER_SANITIZE_* 类型,结果清洗后空了或没效果。它不是万能的——比如 FILTER_SANITIZE_STRING 在 PHP 8.1+ 已被彻底移除,硬写会报 Uncaught ValueError。
常见场景:处理表单里的昵称、地址、搜索关键词这类纯文本输入。
- 用
FILTER_SANITIZE_SPECIAL_CHARS保留换行和空格,只转义<>&等,适合存进数据库前防 XSS - 用
FILTER_SANITIZE_FULL_SPECIAL_CHARS多转义引号(加ENT_QUOTES),适合拼进 HTML 属性值 - 别用
FILTER_SANITIZE_EMAIL做“格式校验”——它只删非法字符,"a@b..c"也能过,真要校验得配FILTER_VALIDATE_EMAIL
示例:
$raw = "<script>alert(1)</script> 张三 "老板""; $clean = filter_var($raw, FILTER_SANITIZE_SPECIAL_CHARS); // 输出:<script>alert(1)</script> 张三 "老板"
数字和邮箱不能只靠 filter_var() 校验
清洗和校验是两件事。filter_var($input, FILTER_VALIDATE_FLOAT) 返回 false 或 float 值,但像 "123abc" 会返回 123.0 —— 它自动截断非法后缀,这在金额录入里就是严重 bug。
立即学习“PHP免费学习笔记(深入)”;
真正安全的做法是先清洗再严格校验:
- 数字:用
filter_var($input, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND)清洗掉字母,再用is_numeric()+ 正则/^-?\d+(\.\d+)?$/确认结构 - 邮箱:先
trim()去首尾空格,再filter_var($email, FILTER_VALIDATE_EMAIL),但必须检查是否为空字符串或只有空格——filter_var(" ", FILTER_VALIDATE_EMAIL)返回false,但" @ "可能意外通过
数组批量清洗容易漏掉嵌套字段
表单提交的多维数组(比如 user[profile][age])用 filter_input_array() 时,如果不显式定义 FILTER_REQUIRE_ARRAY 和递归规则,深层键值根本不会被处理。
正确姿势是手动递归或用 array_walk_recursive() 配合回调:
function sanitize_string($value) {
return is_string($value) ? filter_var($value, FILTER_SANITIZE_SPECIAL_CHARS) : $value;
}
array_walk_recursive($input, function (&$v) { $v = sanitize_string($v); });
注意:array_walk_recursive() 会跳过键名为数字的子数组(如 ["a", ["b"]] 中的 ["b"]),如果业务里用数字索引存对象,得改用自定义递归函数。
清洗后还要注意 MySQL 插入时的编码和长度
清洗只是第一步。比如用 FILTER_SANITIZE_SPECIAL_CHARS 处理中文,输出是 HTML 实体(张三),但数据库字段是 utf8mb4 的话,这些实体反而占更多字节,可能触发 Data too long 错误。
更稳妥的路径是:
- 前端提交前用 UTF-8 编码,后端
mb_convert_encoding($input, 'UTF-8', 'auto')统一源编码 - 清洗后用
mb_strlen($clean, 'UTF-8')检查长度,别用strlen() - 插入前确认字段类型:需要存储 HTML 实体就用
TEXT,要还原显示就该用htmlspecialchars()而非清洗函数
清洗函数不解决字符集错乱,也不保证业务语义合法——比如把电话号码里的 - 全删了,结果变成一长串数字,后续没法分段显示。



















