WordPress下HTML表单+PHP查询外部数据库提交报404问题
问题原因与修复方案
404错误的核心原因
你遇到的404和代码逻辑、文件路径的关系不大,核心是你用了独立PHP文件的开发思路,完全不符合WordPress的运行规则:
- WordPress自带全局URL重写规则,除了根目录下的核心入口文件,直接访问主题/插件目录下的自定义PHP文件会被重写规则拦截,大概率返回404
- 就算你通过调整路径让文件可以被直接访问,这种方式会绕过WordPress的初始化流程,后续会出现数据库连接、权限校验等一系列报错
- 你表单里写的相对路径
action="verify.php"会基于当前访问页面的URL解析路径,如果你把表单放在二级地址的页面下,路径解析会完全错误,必然404
现有代码的其他问题
就算路径问题解决,你现有代码也存在会导致功能失效的问题:
- 存在严重SQL注入漏洞:直接将用户提交的POST参数拼接进SQL语句,没有做任何过滤和参数绑定,极易被恶意攻击拖库
- SQLSRV函数调用错误:混淆了面向对象和面向过程的写法,
$result->sqlsrv_query($con,$query)是错误写法,sqlsrv_query是过程式函数,正确调用方式是传入连接资源作为第一个参数 - 缺失必要的输入校验、结果集释放逻辑,容易出现参数不合法、内存占用过高的问题
WordPress环境下正确实现步骤
不要使用独立的verify.php文件处理请求,用WordPress官方推荐的admin_post钩子处理表单提交,完全规避路径问题:
- 将表单处理逻辑添加到当前主题的
functions.php文件中(或封装为自定义插件),参考代码如下:
// 注册表单提交钩子,同时支持登录/未登录用户访问 add_action('admin_post_nopriv_verify_form', 'handle_verify_form_submit'); add_action('admin_post_verify_form', 'handle_verify_form_submit'); function handle_verify_form_submit() { // 跨站请求伪造校验 if (!wp_verify_nonce($_POST['verify_nonce'], 'verify_form_action')) { wp_die('非法请求'); } // 输入参数格式校验 $number1 = isset($_POST['number1']) ? trim($_POST['number1']) : ''; $number2 = isset($_POST['number2']) ? intval($_POST['number2']) : -1; if (!preg_match('/^[0-9]{8}$/', $number1) || !in_array($number2, [0,1,2,3,4,6,8,10])) { wp_die('输入参数不符合要求'); } // 初始化SQL Server连接,替换为你自己的数据库连接信息 $serverName = "你的数据库地址"; $connectionOptions = [ "Database"=>"你的数据库名", "Uid"=>"数据库账号", "PWD"=>"数据库密码" ]; $con = sqlsrv_connect($serverName, $connectionOptions); if (!$con) { wp_die('数据库连接失败,请确认SQLSRV扩展已启用'); } // 参数化查询,避免SQL注入 $query = "SELECT * FROM dbo.FirstDB WHERE NumberOne = ? AND NumberTwo = ?"; $params = [$number1, $number2]; $result = sqlsrv_query($con, $query, $params); // 抓取查询结果 ob_start(); if ($result && sqlsrv_num_rows($result) > 0) { while ($row = sqlsrv_fetch_array($result)) { for ($i=5; $i<=7; $i++) { if (isset($row[$i]) && $row[$i] > 0) { echo "<h3>Number: </h3>".$row[$i]."<br>"; } } } } else { echo "No Results"; } $result_content = ob_get_clean(); // 释放资源、关闭连接 sqlsrv_free_stmt($result); sqlsrv_close($con); // 结果存入session,跳转回表单页展示,避免表单重复提交 session_start(); $_SESSION['verify_result'] = $result_content; // 将下方地址替换为你实际放置表单的页面地址 wp_redirect(home_url('/替换为你的表单页面路径/')); exit; } // 注册表单短代码,方便在页面编辑器中直接插入 add_shortcode('verify_form', 'render_verify_form'); function render_verify_form() { ob_start(); ?> <form class="verify" name="verify" method="POST" action="<?php echo admin_url('admin-post.php'); ?>"> <input type="hidden" name="action" value="verify_form"> <?php wp_nonce_field('verify_form_action', 'verify_nonce'); ?> <input type="text" autocomplete="off" placeholder="请输入8位数字" name="number1" pattern="^[0-9]{8}$" required maxlength="8"> <select class="number2" name="number2" required> <option value="10">10</option> <option value="8">8</option> <option value="6">6</option> <option value="4">4</option> <option value="3">3</option> <option value="2">2</option> <option value="1">1</option> <option value="0">0</option> </select> <br> <input type="submit" value="提交查询"> </form> <?php // 展示查询结果 session_start(); if (isset($_SESSION['verify_result'])) { echo $_SESSION['verify_result']; unset($_SESSION['verify_result']); } return ob_get_clean(); }
- 不需要再上传独立的verify.php文件,直接在你放表单的WordPress页面编辑器中插入短代码
[verify_form]即可正常使用。 - 部署前请确认线上WordPress的PHP环境已经安装并启用
sqlsrv和pdo_sqlsrv扩展,本地XAMPP默认开启不代表线上环境已启用。
内容的提问来源于stack exchange,提问作者Rinkor16
相关产品推荐
相关产品推荐

