PHP表单提交后保持选中数据库表显示及数据正常写入方案
问题说明
通过下拉表单选择数据库表展示的功能运行正常,但向选中表新增数据提交后,已选中展示的表消失,数据无法写入目标表。
实际运行流程:
- 下拉菜单选择待展示表,点击选择按钮
- 选中的表和对应表单正常加载展示
- 表单填完数据点击提交
- 下拉菜单恢复默认状态,已加载的表消失
- 数据未写入目标表
预期运行流程:
- 下拉菜单选择待展示表,点击选择按钮
- 选中的表和对应表单正常加载展示
- 表单填完数据点击提交
- 选中的表保持展示,数据成功写入对应表
备注:contact_form.php仅适配messages表,不适配messages2表。
涉及代码文件
body.php(主页面)
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Contact Form - PHP/MySQL Demo Code</title> </head> <style> table, th, td { border:1px solid black; } </style> <body> <form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']) ?>" method="post"> <div> <label for="dbselect">Select Table:</label><br> <select name="dbselect" id="dbselect"> <option value=""><-- Choose Table --></option> <option value="messages">messages</option> <option value="messages2">messages2</option> </select> </div> <div> <button type="submit">Select</button> </div> </form> <?php session_start(); include 'get.php'; $_SESSION["dbselect"] = filter_input(INPUT_POST, 'dbselect', FILTER_SANITIZE_STRING); if ($_SESSION["dbselect"] == "messages") { dbMessages("*"); include 'Forms/contact_form.php'; } if ($_SESSION["dbselect"] == "messages2") { dbMessages2("*"); } ?> </body>
get.php(表内容渲染输出)
<?php function display_data($data) { $output = "<table>"; foreach($data as $key => $var) { //$output .= '<tr>'; if($key===0) { $output .= '<tr>'; foreach($var as $col => $val) { $output .= "<td>" . $col . '</td>'; } $output .= '</tr>'; foreach($var as $col => $val) { $output .= '<td>' . $val . '</td>'; } $output .= '</tr>'; } else { $output .= '<tr>'; foreach($var as $col => $val) { $output .= '<td>' . $val . '</td>'; } $output .= '</tr>'; } } $output .= '</table>'; echo $output; } function dbMessages($selector) { include 'db.php'; $query = "SELECT $selector FROM messages"; $res = mysqli_query($conn,$query); display_data($res); } function dbMessages2($selector) { include 'db.php'; $query = "SELECT $selector FROM messages2"; $res = mysqli_query($conn,$query); display_data($res); }
contact_form.php(新增数据表单)
<?php include 'db.php'; if ((isset($_POST["Submit"])) && (!empty($_POST["txtName"])) && (!empty($_POST["txtPhone"])) && (!empty($_POST["txtEmail"])) && (!empty($_POST["txtMessage"]))) { $txtName = $_POST['txtName']; $txtEmail = $_POST['txtEmail']; $txtPhone = $_POST['txtPhone']; $txtMessage = $_POST['txtMessage']; $query = "insert into messages(ID, name, email, phone, message) values (NULL, '$txtName', '$txtEmail', '$txtPhone', '$txtMessage')"; $res = mysqli_query($conn , $query); mysqli_close($conn); unset($_POST); echo "<meta http-equiv='refresh' content='0'>"; } echo ' <fieldset> <legend>Contact Form</legend> <form name="frmContact" method="post" action="index.php?send=1" target="_self"> <p> <label for="Name">Name </label> <input type="text" name="txtName" id="txtName" > </p> <p> <label for="email">Email</label> <input type="text" name="txtEmail" id="txtEmail"> </p> <p> <label for="phone">Phone</label> <input type="text" name="txtPhone" id="txtPhone"> </p> <p> <label for="message">Message</label> <textarea name="txtMessage" id="txtMessage"></textarea> </p> <p> </p> <p> <input type="submit" name="Submit" id="Submit" value="Submit"> </p> </form> </fieldset> ' ?>
问题原因
- 会话赋值逻辑错误:
body.php每次加载都会无条件用POST参数覆盖$_SESSION["dbselect"],提交新增表单时请求里没有dbselect参数,直接把会话中存储的选中表值覆盖为空,无法加载对应表内容。 - 会话启动位置错误:
session_start()放在HTML输出之后,会触发"headers already sent"错误,导致会话无法正常读写。 - 表单提交地址错误:
contact_form.php的表单action写死为index.php?send=1,但主页面文件是body.php,提交后请求发到错误路径,逻辑无法正常执行。 - 重复引入数据库连接:多个函数重复
include 'db.php',容易引发连接变量重复定义的错误。 - SQL拼接风险:直接把用户输入拼接到INSERT语句中,没有转义特殊字符,既存在SQL注入风险,也容易因为输入内容包含特殊字符导致SQL执行失败。
修复方案
1. 修改body.php
把session_start()移到文件最开头,仅当POST请求中存在dbselect参数时才更新会话值,同时给下拉菜单增加选中状态保持。
修复后代码:
<?php session_start(); ?> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Contact Form - PHP/MySQL Demo Code</title> </head> <style> table, th, td { border:1px solid black; } </style> <body> <form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']) ?>" method="post"> <div> <label for="dbselect">Select Table:</label><br> <select name="dbselect" id="dbselect"> <option value="" <?php echo (($_SESSION["dbselect"] ?? "") == "") ? "selected" : ""; ?>><-- Choose Table --></option> <option value="messages" <?php echo (($_SESSION["dbselect"] ?? "") == "messages") ? "selected" : ""; ?>>messages</option> <option value="messages2" <?php echo (($_SESSION["dbselect"] ?? "") == "messages2") ? "selected" : ""; ?>>messages2</option> </select> </div> <div> <button type="submit">Select</button> </div> </form> <?php include 'get.php'; // 仅当提交了表选择参数时才更新会话 if (isset($_POST['dbselect'])) { $_SESSION["dbselect"] = filter_input(INPUT_POST, 'dbselect', FILTER_SANITIZE_STRING); } $currentTable = $_SESSION["dbselect"] ?? ""; if ($currentTable == "messages") { dbMessages("*"); include 'Forms/contact_form.php'; } if ($currentTable == "messages2") { dbMessages2("*"); } ?> </body>
2. 修改get.php
把数据库连接文件的引入改为include_once,避免重复引入报错,同时给查询增加错误判断:
<?php include_once 'db.php'; function display_data($data) { $output = "<table>"; foreach($data as $key => $var) { if($key===0) { $output .= '<tr>'; foreach($var as $col => $val) { $output .= "<td>" . $col . '</td>'; } $output .= '</tr>'; foreach($var as $col => $val) { $output .= '<td>' . $val . '</td>'; } $output .= '</tr>'; } else { $output .= '<tr>'; foreach($var as $col => $val) { $output .= '<td>' . $val . '</td>'; } $output .= '</tr>'; } } $output .= '</table>'; echo $output; } function dbMessages($selector) { global $conn; $query = "SELECT $selector FROM messages"; $res = mysqli_query($conn,$query); if ($res) { display_data($res); } } function dbMessages2($selector) { global $conn; $query = "SELECT $selector FROM messages2"; $res = mysqli_query($conn,$query); if ($res) { display_data($res); } }
3. 修改contact_form.php
修正表单提交地址,改用预处理语句执行INSERT避免SQL注入,提交后通过跳转重载页面避免重复提交:
<?php global $conn; if ((isset($_POST["Submit"])) && (!empty($_POST["txtName"])) && (!empty($_POST["txtPhone"])) && (!empty($_POST["txtEmail"])) && (!empty($_POST["txtMessage"]))) { $txtName = trim($_POST['txtName']); $txtEmail = trim($_POST['txtEmail']); $txtPhone = trim($_POST['txtPhone']); $txtMessage = trim($_POST['txtMessage']); // 用预处理语句防止注入 $stmt = mysqli_prepare($conn, "insert into messages(ID, name, email, phone, message) values (NULL, ?, ?, ?, ?)"); mysqli_stmt_bind_param($stmt, "ssss", $txtName, $txtEmail, $txtPhone, $txtMessage); mysqli_stmt_execute($stmt); mysqli_stmt_close($stmt); // 提交后跳转到当前页,避免重复提交 header("Location: ".$_SERVER['PHP_SELF']); exit; } ?> <fieldset> <legend>Contact Form</legend> <form name="frmContact" method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" target="_self"> <p> <label for="Name">Name </label> <input type="text" name="txtName" id="txtName" > </p> <p> <label for="email">Email</label> <input type="text" name="txtEmail" id="txtEmail"> </p> <p> <label for="phone">Phone</label> <input type="text" name="txtPhone" id="txtPhone"> </p> <p> <label for="message">Message</label> <textarea name="txtMessage" id="txtMessage"></textarea> </p> <p> </p> <p> <input type="submit" name="Submit" id="Submit" value="Submit"> </p> </form> </fieldset>
修改完成后,提交新增数据时会保留当前选中的表状态,数据可正常写入,页面不会重置。
内容的提问来源于stack exchange,提问作者Gabriel
相关产品推荐
相关产品推荐

