PHP开发Quiz/Madlibs类网站:表单验证失效,空值/特殊字符仍可提交求解
代码存在的核心问题
- 正则表达式逻辑完全写反
你当前写的校验规则为:
实际逻辑偏差点:if(!preg_match("/[^a-z0-9 _]+$/i", $Input1)){ $Input1Err = "only letters and white space allowed"; }- 正则
/[^a-z0-9 _]+$/i的含义是:匹配字符串末尾存在至少一个不属于字母、数字、空格、下划线的字符 - 配合外层
!取反判断,逻辑变成:如果输入里没有“末尾的特殊字符”,就抛出特殊字符报错 - 比如输入
?时,这个字符串本身就是位于末尾的特殊字符,正则会匹配成功返回true,取反后变成false,根本不会进入报错分支,直接放过了特殊字符输入 - 该正则只检查字符串末尾,哪怕输入中间有特殊字符,只要末尾是合法字符,也会直接通过
- 正则
- 没有设置全局校验通过判断
你在输出最终结果的分支里,只要是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
相关产品推荐
相关产品推荐

