You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP开发Quiz/Madlibs类网站:表单验证失效,空值/特殊字符仍可提交求解

代码存在的核心问题
  • 正则表达式逻辑完全写反
    你当前写的校验规则为:
    if(!preg_match("/[^a-z0-9 _]+$/i", $Input1)){
      $Input1Err = "only letters and white space allowed";
    }
    
    实际逻辑偏差点:
    1. 正则/[^a-z0-9 _]+$/i的含义是:匹配字符串末尾存在至少一个不属于字母、数字、空格、下划线的字符
    2. 配合外层!取反判断,逻辑变成:如果输入里没有“末尾的特殊字符”,就抛出特殊字符报错
    3. 比如输入?时,这个字符串本身就是位于末尾的特殊字符,正则会匹配成功返回true,取反后变成false,根本不会进入报错分支,直接放过了特殊字符输入
    4. 该正则只检查字符串末尾,哪怕输入中间有特殊字符,只要末尾是合法字符,也会直接通过
  • 没有设置全局校验通过判断
    你在输出最终结果的分支里,只要是POST请求就直接展示填词结果,完全没有检查所有输入项的错误变量($Input1Err到$Input7Err)是否全部为空,哪怕存在校验错误,也不会拦截结果展示
  • 验证逻辑被完全覆盖
    在POST请求处理的结果展示分支里,你直接重新从$_POST里取值覆盖了之前经过test_input处理、完成校验的$Input变量,等于之前写的输入清洗、校验流程全部失效
  • 函数定义位置不规范
    你把test_input函数定义在了if ($_SERVER["REQUEST_METHOD"] == "POST")的代码块内部,虽然PHP可以解析,但后续如果逻辑调整很容易出现作用域访问的问题
修改方案
  • 修正正则校验逻辑
    把允许输入的规则调整为:整个字符串从头到尾只允许出现字母、数字、空格、下划线,对应的正确正则是/^[a-z0-9 _]+$/i。这个正则的含义是:从字符串开头^到结尾$,所有字符都必须是匹配[a-z0-9 _]范围内的内容,判断逻辑直接调整为如果正则不匹配就抛出特殊字符报错,不需要多余取反。
  • 增加全局校验状态判断
    新增一个标志位(比如$validatePass),初始值为true,只要任意一个输入项触发了错误,就把这个标志位设为false。
  • 修正结果展示逻辑
    只有当全局校验通过($validatePass为true)时,才展示最终的填词结果;否则重新展示表单,并且在每个输入框下方显示对应的错误提示。
  • 优化代码结构
    把重复的校验逻辑封装成循环,不用为7个输入项重复写一模一样的判断代码;把test_input函数移到代码全局位置,避免作用域问题。
可直接复用的修正后核心代码示例
<?php
// 定义所有需要校验的输入项名称
$inputKeys = ["Input1", "Input2", "Input3", "Input4", "Input5", "Input6", "Input7"];
// 初始化输入值、错误信息数组
$userInputs = [];
$inputErrors = [];
foreach ($inputKeys as $key) {
    $userInputs[$key] = "";
    $inputErrors[$key] = "";
}
$validatePass = true;

// 定义输入清洗函数,放在全局作用域
function test_input($data) {
  $data = trim($data);
  $data = stripslashes($data);
  $data = htmlspecialchars($data);
  return $data;
}

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    foreach ($inputKeys as $key) {
        // 校验空值
        if(empty(trim($_POST[$key]))){
            $inputErrors[$key] = "请输入内容,不能为空";
            $validatePass = false;
            continue;
        }
        // 清洗输入
        $userInputs[$key] = test_input($_POST[$key]);
        // 校验特殊字符:整个字符串只允许字母、数字、空格、下划线
        if(!preg_match("/^[a-z0-9 _]+$/i", $userInputs[$key])){
            $inputErrors[$key] = "仅允许输入字母、数字、空格或下划线";
            $validatePass = false;
        }
    }

    // 仅当所有校验通过时展示结果
    if ($validatePass) {
        $i1 = $userInputs["Input1"];
        $i2 = $userInputs["Input2"];
        $i3 = $userInputs["Input3"];
        $i4 = $userInputs["Input4"];
        $i5 = $userInputs["Input5"];
        $i6 = $userInputs["Input6"];
        $i7 = $userInputs["Input7"];
        echo "Driving a car can be fun if you follow this $i1. advice:
        When approaching a $i2 on the right, always blow your $i4 Before making a
        $i3 turn, always stick your $i2 out of the window.
        Every 2000 miles, have your $i1 inspected and your $i5 checked.
        When approaching a school, watch out for $i6. 
       Above all, drive $i6 the $i7 you save may be your own!$i2";
        exit;
    }
}
?>

<!-- 表单部分(校验不通过或GET请求时展示) -->
<form action="<?= htmlspecialchars($_SERVER["PHP_SELF"]);?>" method="POST">
    <h1>Quiz</h1>
    <?php foreach ($inputKeys as $index => $key): ?>
    <p>
        Question.. 
        <input type="text" name="<?= $key ?>" placeholder="enter here" value="<?= $userInputs[$key] ?>">
        <span style="color:red">* <?= $inputErrors[$key] ?></span>
    </p> 
    <?php endforeach; ?>
    <input type="submit" name="submit" value="Send">
</form>

内容的提问来源于stack exchange,提问作者user14541933

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.01 02:06:07