filter_var() 是 PHP 最稳的基础类型校验方案,支持邮箱、整数、URL 等严格验证,比 is_int() 和正则更可靠;需配合 isset() 检查必填字段,抛 InvalidArgumentException;批量校验用 filter_var_array();复杂业务规则应封装为独立函数。

用 filter_var() 做基础类型校验最稳
PHP 自带的 filter_var() 不依赖框架、不引入额外包,对字符串、整数、邮箱、URL 等常见类型校验既快又准。它比手写正则或 is_int() 更可靠——比如 is_int("123") 返回 false,但 filter_var("123", FILTER_VALIDATE_INT) 能正确转成整型并验证。
常见用法:
-
filter_var($email, FILTER_VALIDATE_EMAIL):严格按 RFC 验证邮箱格式,不接受test@localhost -
filter_var($id, FILTER_VALIDATE_INT, ["options" => ["min_range" => 1]]):带范围限制的整数校验 -
filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED):要求 URL 必须含路径(如拒绝http://example.com)
注意:它默认不处理空字符串或 null,需先用 isset() 或 array_key_exists() 判断键是否存在,否则直接传 null 可能静默失败。
必填字段缺失时抛 InvalidArgumentException
接口参数缺失不是“数据不对”,而是“契约破坏”,该立刻中断。用 InvalidArgumentException 比 Exception 更语义明确,也方便上层统一捕获处理。
立即学习“PHP免费学习笔记(深入)”;
示例逻辑:
if (!isset($_POST['username']) || trim($_POST['username']) === '') {
throw new InvalidArgumentException('username is required');
}
别用 empty() 判空——它会把 "0"、0、false 都当空,而用户名可能是数字字符串 "0";也别只判 isset(),因为 $_POST['field'] = "" 是存在的但无效。
真实场景中,建议封装一个 requireParam(string $key, array $data) 函数,内部做 array_key_exists() + trim() !== '' 双检,避免重复写。
批量校验用 filter_var_array() 避免循环调用
当一次要校验十多个字段(如用户注册接口),逐个调用 filter_var() 不仅啰嗦,还容易漏掉某个字段的选项配置。用 filter_var_array() 一次性声明规则,清晰且性能更好。
示例:
$rules = [
'email' => FILTER_VALIDATE_EMAIL,
'age' => ['filter' => FILTER_VALIDATE_INT, 'options' => ['min_range' => 1, 'max_range' => 120]],
'url' => ['filter' => FILTER_VALIDATE_URL, 'flags' => FILTER_FLAG_PATH_REQUIRED]
];
$result = filter_var_array($_POST, $rules);
返回数组中,校验失败的字段值为 false 或 null(取决于 FILTER_NULL_ON_FAILURE 标志)。注意:它不会自动过滤掉缺失键,所以仍需提前检查必要键是否存在。
陷阱:不要在规则里混用 FILTER_SANITIZE_* 和 FILTER_VALIDATE_*——前者返回处理后值,后者返回布尔,结果类型不一致,后续判断容易出错。
复杂规则(如密码强度、手机号归属地)必须抽离成独立函数
邮箱、整数这些有标准定义,但“密码至少含大小写字母+数字+特殊字符”或“手机号前三位必须是 13x/15x/18x”这种业务规则,硬塞进 filter_var() 或一堆 if 里,会导致校验逻辑散落、难以复用、测试困难。
做法很简单:
- 写函数如
isValidPassword(string $pwd): bool,只专注一条规则 - 在主校验流程中调用,失败时统一抛
InvalidArgumentException并附具体提示 - 把这类函数放进
src/Validator/目录,和控制器解耦
别图省事在接口里写正则校验密码:preg_match('/^(?=.*[a-z])(?=.*[A-Z]).../', $pwd) ——可读性差,改规则时极易出错,也没法单独测。
真正难的不是写校验代码,是让每条规则有明确归属、可被复用、出错时提示够具体。校验逻辑一旦开始“拼凑”,后面加字段、改需求就会越来越卡。



















