首页 / PHP 入门教程 / PHP 过滤器

PHP 入门教程

PHP 过滤器

本教程共 65 篇 · 第 32 篇 · 更新于 2026-07-24 · 约 5 分钟阅读

PHPPHP8过滤器filter_var数据净化XSS

32. PHP 过滤器

本节目标:熟练使用 filter_varfilter_input,区分验证(Validate)与净化(Sanitize),处理常见数据类型。

用户输入的数据往往”鱼龙混杂”。PHP 过滤器扩展提供了一套标准工具,帮你验证格式是否正确,或清理掉不安全的字符。

32.1 验证 vs 净化

类型作用示例
验证(Validate)检查数据是否符合格式,返回原值或 false邮箱格式对不对
净化(Sanitize)移除非法字符,返回清理后的值去掉标签、转义特殊符号
<?php
$email = "test@example.com<script>";

// 验证:格式不对就返回 false
$valid = filter_var($email, FILTER_VALIDATE_EMAIL);
var_dump($valid); // false

// 净化:移除非法字符
$clean = filter_var($email, FILTER_SANITIZE_EMAIL);
echo $clean; // test@example.comscript
Note

净化不保证格式正确,只是清理字符。重要数据应该先净化再验证

32.2 filter_var() 验证常用类型

<?php
// 整数
$age = "25";
var_dump(filter_var($age, FILTER_VALIDATE_INT));      // int(25)
var_dump(filter_var("abc", FILTER_VALIDATE_INT));     // false

// 布尔值
$flag = "yes";
var_dump(filter_var($flag, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // bool(true)

// 浮点数
$price = "19.99";
var_dump(filter_var($price, FILTER_VALIDATE_FLOAT));  // float(19.99)

// IP 地址
$ip = "192.168.1.1";
var_dump(filter_var($ip, FILTER_VALIDATE_IP));        // string(...)
var_dump(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)); // 仅 IPv4

// MAC 地址
$mac = "00:1A:2B:3C:4D:5E";
var_dump(filter_var($mac, FILTER_VALIDATE_MAC));      // string(...)

32.3 filter_var() 净化常用类型

<?php
$input = "<p>Hello <script>alert('xss')</script> World!</p>";

// 编码特殊字符(防 XSS,等价于 htmlspecialchars)
$encoded = filter_var($input, FILTER_SANITIZE_SPECIAL_CHARS);
echo $encoded;
// 输出:&lt;p&gt;Hello &lt;script&gt;alert(&#039;xss&#039;)&lt;/script&gt; World!&lt;/p&gt;

// 只保留允许的标签(真正移除标签)
$allowedTags = "<p><br><strong>";
$safe = strip_tags($input, $allowedTags);
echo $safe;

// 另一个选择:完整编码所有特殊字符
$fullEncoded = filter_var($input, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
echo $fullEncoded;
Tip

FILTER_SANITIZE_FULL_SPECIAL_CHARShtmlspecialchars() 的过滤器版本,PHP 8.1 起推荐使用。

32.4 用 filter_input() 直接处理超全局变量

filter_input() 比直接访问 $_GET/$_POST 更安全,因为它不会触发未定义索引的警告:

<?php
// 获取 GET 参数并验证为整数
$page = filter_input(INPUT_GET, "page", FILTER_VALIDATE_INT) ?: 1;

// 获取 POST 邮箱并验证
$email = filter_input(INPUT_POST, "email", FILTER_VALIDATE_EMAIL);
if ($email === false) {
    echo "邮箱格式错误";
}

// 获取 COOKIE 并净化
$username = filter_input(INPUT_COOKIE, "user", FILTER_SANITIZE_SPECIAL_CHARS);

输入类型常量

常量对应超全局变量
INPUT_GET$_GET
INPUT_POST$_POST
INPUT_COOKIE$_COOKIE
INPUT_SERVER$_SERVER
INPUT_ENV$_ENV

32.5 过滤数组:filter_var_array()

批量过滤表单数据非常方便:

<?php
$filters = [
    "name"     => [
        "filter"  => FILTER_SANITIZE_SPECIAL_CHARS,
        "flags"   => FILTER_FLAG_STRIP_LOW,
    ],
    "age"      => [
        "filter"  => FILTER_VALIDATE_INT,
        "options" => ["min_range" => 1, "max_range" => 150],
    ],
    "email"    => FILTER_VALIDATE_EMAIL,
    "website"  => FILTER_VALIDATE_URL,
    "score"    => FILTER_VALIDATE_FLOAT,
];

$result = filter_var_array($_POST, $filters);

if ($result["age"] === false) {
    echo "年龄必须在 1-150 之间";
}

if ($result["email"] === false) {
    echo "邮箱格式不正确";
}
Note

验证失败时,对应字段返回 false。若字段不存在,返回 null。注意区分 falsenull

32.6 自定义过滤回调

<?php
$input = "  Hello World 123!  ";

// 使用回调自定义过滤逻辑
$result = filter_var($input, FILTER_CALLBACK, [
    "options" => function (string $value): string {
        return preg_replace('/[^a-zA-Z\s]/', '', trim($value));
    }
]);

echo $result; // Hello World

32.7 常见错误提醒

  • 混淆验证与净化结果:验证失败返回 false,净化总是返回字符串
  • 整数验证的 0 陷阱filter_var("0", FILTER_VALIDATE_INT) 返回 0,判断时要用 === false
  • URL 验证需带协议example.com 不会通过 FILTER_VALIDATE_URL,必须是 http://example.com

来源:参考了 runoob「PHP 过滤器」「PHP 高级过滤器」、w3cschool「PHP 过滤器」「PHP 高级过滤器」等,改写后所得。