
在开发动态 web 应用时,用户选择和数据提交是常见交互。本案例中,用户期望通过下拉菜单选择一个数据库表进行显示,并在该表对应的表单中提交数据。然而,实际操作中出现了两个主要问题:
这两个问题根源在于 PHP 会话管理的不当以及表单处理逻辑的缺陷。
原始的 body.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("*");
}
// ...问题在于 $_SESSION["dbselect"] = filter_input(INPUT_POST, 'dbselect', FILTER_SANITIZE_STRING); 这一行。它在每次页面加载时都会无条件执行。当用户提交 数据输入表单 时,$_POST['dbselect'] 将不存在,导致 filter_input 返回 NULL 或空字符串,从而覆盖了之前存储在 $_SESSION["dbselect"] 中的正确表格选择。结果就是,页面刷新后 $_SESSION["dbselect"] 失去其值,表格不再显示。
此外,FILTER_SANITIZE_STRING 过滤器在 PHP 8.1.0 版本中已被弃用,不应再使用。
立即学习“PHP免费学习笔记(深入)”;
原始的 contact_form.php 代码片段如下:
// ...
<form name="frmContact" method="post" action="index.php?send=1" target="_self">
// ...
$query = "insert into messages(ID, name, email, phone, message) values (NULL,
'$txtName', '$txtEmail', '$txtPhone', '$txtMessage')";
// ...这里存在两个问题:
为了解决上述问题,我们需要对 body.php 和 contact_form.php 进行关键性修改。
核心思想是只有当用户明确通过下拉菜单提交了表格选择时,才更新 $_SESSION["dbselect"]。
<?php
session_start(); // 确保在任何输出之前调用
include 'get.php'; // 包含显示表格的函数
// 仅当 'dbselect' 表单字段被提交时,才更新会话变量
if (isset($_POST["dbselect"])) {
// 直接使用 $_POST,因为我们期望它来自下拉菜单,并且后续用于匹配,无需复杂过滤
$_SESSION["dbselect"] = $_POST["dbselect"];
}
// 获取当前选定的表名,如果会话中没有,则默认为空
$selected_table = $_SESSION["dbselect"] ?? '';
?>
<!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" <?php echo ($selected_table === 'messages') ? 'selected' : ''; ?>>messages</option>
<option value="messages2" <?php echo ($selected_table === 'messages2') ? 'selected' : ''; ?>>messages2</option>
</select>
</div>
<div>
<button type="submit">Select</button>
</div>
</form>
<?php
// 根据会话中存储的表格名称显示相应的表格和表单
if ($selected_table === "messages") {
dbMessages("*");
include 'Forms/contact_form.php'; // 包含联系表单
} elseif ($selected_table === "messages2") {
dbMessages2("*");
// 如果 messages2 也有对应的表单,应在此处包含
}
?>
</body>
</html>修改说明:
为了让 contact_form.php 能够动态地向选定的表插入数据,并确保数据提交后状态不丢失,我们需要进行以下调整:
<?php
// 确保在任何输出之前调用 session_start(),如果 body.php 已经调用,这里可以省略,但为了模块化,最好包含
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
include 'db.php'; // 包含数据库连接文件
// 从会话中获取当前选定的表名
$targetTable = $_SESSION["dbselect"] ?? '';
// 只有当目标表有效且为 'messages' 时,才允许处理表单提交
// 注意:原问题中提到 contact_form.php 仅用于 messages 表。
// 如果 messages2 也有表单,需要复制此文件并修改逻辑,或使此文件更通用。
if ($targetTable !== 'messages') {
// 如果不是 messages 表,则不显示或不处理此表单
// 或者可以抛出错误,或者直接返回
echo "<p style='color:red;'>此表单仅适用于 'messages' 表。</p>";
return; // 停止执行,不显示表单
}
if (isset($_POST["Submit"])) {
// 检查所有必填字段是否都已提交且不为空
if (!empty($_POST["txtName"]) && !empty($_POST["txtPhone"]) && !empty($_POST["txtEmail"]) && !empty($_POST["txtMessage"])) {
// 使用 mysqli_real_escape_string (不推荐,但比直接拼接好,最佳是预处理)
// 更好的方法是使用预处理语句,如下所示
$txtName = htmlspecialchars($_POST['txtName']);
$txtEmail = htmlspecialchars($_POST['txtEmail']);
$txtPhone = htmlspecialchars($_POST['txtPhone']);
$txtMessage = htmlspecialchars($_POST['txtMessage']);
// 准备 SQL 插入语句 - 使用预处理语句防止 SQL 注入
$stmt = mysqli_prepare($conn, "INSERT INTO " . $targetTable . "(name, email, phone, message) VALUES (?, ?, ?, ?)");
if ($stmt) {
// 绑定参数
mysqli_stmt_bind_param($stmt, "ssss", $txtName, $txtEmail, $txtPhone, $txtMessage);
// 执行语句
if (mysqli_stmt_execute($stmt)) {
echo "<p style='color:green;'>数据已成功添加到 " . htmlspecialchars($targetTable) . " 表。</p>";
} else {
echo "<p style='color:red;'>数据添加失败: " . mysqli_error($conn) . "</p>";
}
// 关闭语句
mysqli_stmt_close($stmt);
} else {
echo "<p style='color:red;'>SQL 预处理失败: " . mysqli_error($conn) . "</p>";
}
} else {
echo "<p style='color:orange;'>请填写所有必填字段。</p>";
}
// 清除 POST 数据,防止刷新重复提交
// unset($_POST); // 不推荐直接 unset $_POST,因为可能影响其他逻辑
// 更好的做法是重定向到当前页面,但这里我们只是刷新显示
// 刷新页面以显示更新后的数据,并确保表格选择状态保持
echo "<meta http-equiv='refresh' content='0;url=" . htmlspecialchars($_SERVER['PHP_SELF']) . "'>";
exit; // 确保在重定向后停止执行
}
// 如果是 GET 请求或提交失败,显示表单
echo '
<fieldset>
<legend>Contact Form</legend>
<form name="frmContact" method="post" action="' . htmlspecialchars($_SERVER['PHP_SELF']) . '" target="_self">
<p>
<label for="Name">Name </label>
<input type="text" name="txtName" id="txtName" value="' . (isset($_POST['txtName']) ? htmlspecialchars($_POST['txtName']) : '') . '">
</p>
<p>
<label for="email">Email</label>
<input type="text" name="txtEmail" id="txtEmail" value="' . (isset($_POST['txtEmail']) ? htmlspecialchars($_POST['txtEmail']) : '') . '">
</p>
<p>
<label for="phone">Phone</label>
<input type="text" name="txtPhone" id="txtPhone" value="' . (isset($_POST['txtPhone']) ? htmlspecialchars($_POST['txtPhone']) : '') . '">
</p>
<p>
<label for="message">Message</label>
<textarea name="txtMessage" id="txtMessage">' . (isset($_POST['txtMessage']) ? htmlspecialchars($_POST['txtMessage']) : '') . '</textarea>
</p>
<p> </p>
<p>
<input type="submit" name="Submit" id="Submit" value="Submit">
</p>
</form>
</fieldset>
';
// 数据库连接在处理完请求后关闭
mysqli_close($conn);
?>修改说明:
get.php 负责从数据库获取并显示数据,db.php 负责数据库连接。这两个文件在原始代码中似乎工作正常,但为了完整性,这里提供一个简化的 db.php 示例和 get.php 的关键部分。
db.php 示例:
<?php
$servername = "localhost";
$username = "your_username";
$password = "your_password";
$dbname = "your_database";
// 创建连接
$conn = mysqli_connect($servername, $username, $password, $dbname);
// 检查连接
if (!$conn) {
die("连接失败: " . mysqli_connect_error());
}
?>get.php 关键部分:
<?php
function display_data($result) { // 接收 mysqli_result 对象
if (!$result || mysqli_num_rows($result) === 0) {
echo "<p>没有数据可显示。</p>";
return;
}
$output = "<table border='1'>";
$header_printed = false;
while ($row = mysqli_fetch_assoc($result)) {
if (!$header_printed) {
$output .= '<tr>';
foreach ($row as $col => $val) {
$output .= "<th>" . htmlspecialchars($col) . '</th>';
}
$output .= '</tr>';
$header_printed = true;
}
$output .= '<tr>';
foreach ($row as $col => $val) {
$output .= '<td>' . htmlspecialchars($val) . '</td>';
}
$output .= '</tr>';
}
$output .= '</table>';
echo $output;
mysqli_free_result($result); // 释放结果集
}
function dbMessages($selector) {
include 'db.php'; // 确保每次函数调用都能获取到 $conn
$query = "SELECT $selector FROM messages";
$res = mysqli_query($conn, $query);
if ($res) {
display_data($res);
} else {
echo "<p style='color:red;'>查询 'messages' 表失败: " . mysqli_error($conn) . "</p>";
}
// mysqli_close($conn); // 不在此处关闭,因为可能其他函数还需要 $conn
}
function dbMessages2($selector) {
include 'db.php以上就是PHP 动态表格选择与数据持久化教程的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号