AJAX 数据库
PHP - AJAX 与数据库交互
Section titled “PHP - AJAX 与数据库交互”AJAX(异步 JavaScript 和 XML)允许网页在后台与服务器通信,而无需进行完整的页面重新加载。这使得动态和交互式用户体验成为可能,例如即时获取数据库信息。
现代 AJAX 通常使用 JavaScript 的 fetch API,并且常用 JSON 代替 XML 进行数据交换,尽管核心概念保持不变。
AJAX 数据库示例:获取用户详情
Section titled “AJAX 数据库示例:获取用户详情”本示例演示了如何通过从下拉列表中选择一个用户来触发 AJAX 请求到 PHP 脚本,然后该脚本查询 MySQL 数据库并将用户的详情返回到页面上显示。
概念性用户界面:
**Person info will be listed here...**
MySQL 数据库表
Section titled “MySQL 数据库表”假设我们的数据库中有一个 users 表,其结构和数据如下:
CREATE TABLE users ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, FirstName VARCHAR(50) NOT NULL, LastName VARCHAR(50) NOT NULL, Age INT, Hometown VARCHAR(50), Job VARCHAR(50), INDEX(LastName) -- 示例索引);
INSERT INTO users (FirstName, LastName, Age, Hometown, Job) VALUES('Peter', 'Griffin', 41, 'Quahog', 'Brewery'),('Lois', 'Griffin', 40, 'Newport', 'Piano Teacher'),('Joseph', 'Swanson', 39, 'Quahog', 'Police Officer'),('Glenn', 'Quagmire', 41, 'Quahog', 'Pilot');表数据:
| ID | 名 | 姓 | 年龄 | 家乡 | 职业 |
|---|---|---|---|---|---|
| 1 | Peter | Griffin | 41 | Quahog | Brewery |
| 2 | Lois | Griffin | 40 | Newport | Piano Teacher |
| 3 | Joseph | Swanson | 39 | Quahog | Police Officer |
| 4 | Glenn | Quagmire | 41 | Quahog | Pilot |
示例讲解:HTML 和 JavaScript (客户端)
Section titled “示例讲解:HTML 和 JavaScript (客户端)”HTML 设置了下拉列表。使用 fetch API 的 JavaScript 监听下拉列表的 change 事件,将选定的用户 ID 发送到服务器,并用服务器响应更新 txtHint div。
文件:index.html(或 .php)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>AJAX Database Example</title> <style> #txtHint table { width: 100%; border-collapse: collapse; } #txtHint table, #txtHint th, #txtHint td { border: 1px solid black; padding: 5px; text-align: left; } </style></head><body>
<h1>Select User</h1><form> <label for="user-select">Select a person:</label> <select name="users" id="user-select"> <option value="">Select a person:</option> <option value="1">Peter Griffin</option> <option value="2">Lois Griffin</option> <option value="3">Joseph Swanson</option> <option value="4">Glenn Quagmire</option> </select></form><br><div id="txtHint">**Person info will be listed here...**</div>
<script> // 等待 DOM 完全加载 document.addEventListener('DOMContentLoaded', function() { const userSelect = document.getElementById('user-select'); const hintContainer = document.getElementById('txtHint');
userSelect.addEventListener('change', function() { const userId = this.value; hintContainer.innerHTML = '**Loading...**'; // 提供反馈
if (userId === "") { hintContainer.innerHTML = "**Person info will be listed here..."; return; }
// 使用 Fetch API 向 PHP 后端发送请求 fetch(`get_user.php?q=${encodeURIComponent(userId)}`) // 使用 encodeURIComponent 以确保安全 .then(response => { if (!response.ok) { // 处理 HTTP 错误(例如 404, 500) throw new Error(`HTTP error! Status: ${response.status}`); } return response.text(); // 将响应主体获取为文本(本例中为 HTML) }) .then(html => { // 使用从服务器接收到的 HTML 更新 hint 容器 hintContainer.innerHTML = html; }) .catch(error => { // 处理 fetch 错误(网络问题等)或服务器错误 console.error('Fetch Error:', error); hintContainer.innerHTML = `**加载数据出错: ${error.message}**`; }); }); });</script>
</body></html>JavaScript 讲解:
- 给
<select>元素的change事件附加了一个事件监听器。 - 当用户选择一个选项时,会获取选定的
userId。 - 如果
userId为空,则重置提示区域。 fetch()函数向get_user.php发送一个异步 GET 请求。userId作为 URL 参数q传递。encodeURIComponent()确保值安全地添加到 URL 中。.then(response => ...)处理服务器的响应。它检查响应状态是否为 OK(例如 200)。.then(html => ...)处理响应主体(预期是 HTML 文本),并更新txtHintdiv 的innerHTML。.catch(error => ...)处理 fetch 过程中的任何错误(例如网络错误、服务器错误)。- 提供“Loading…”反馈可以改善用户体验。
PHP 脚本 (服务器端):get_user.php
Section titled “PHP 脚本 (服务器端):get_user.php”此 PHP 脚本接收用户 ID(q),连接到数据库,使用预处理语句****安全地查询数据库,将结果格式化为 HTML 表格,然后发送回浏览器。
**安全警告:**处理用户输入进行数据库查询时,务必始终使用预处理语句,以防止 SQL 注入漏洞。
<?phpdeclare(strict_types=1);
// --- 数据库配置 ---// !! 重要:安全地存储凭据,不要直接放在代码中。// 考虑使用环境变量或放在网站根目录外的配置文件。$dbHost = 'localhost';$dbUser = 'your_db_username'; // 替换为你的数据库用户名$dbPass = 'your_db_password'; // 替换为你的数据库密码$dbName = 'your_database_name'; // 替换为你的数据库名
// --- 从请求获取用户 ID ---// 使用 filter_input 更安全地访问 GET/POST 变量$userId = filter_input(INPUT_GET, 'q', FILTER_VALIDATE_INT);
if ($userId === false || $userId === null) { // 处理无效或缺失的 ID - 优雅地退出或返回错误消息 // 设置 HTTP 响应码有助于客户端脚本 // http_response_code(400); // 错误请求 echo "Invalid user ID provided."; exit;}
// --- 数据库连接(以 MySQLi 过程式风格为例)---$conn = mysqli_connect($dbHost, $dbUser, $dbPass, $dbName);
// 检查连接if (!$conn) { // 在内部记录详细错误,向用户显示通用消息 error_log("Database Connection Error: " . mysqli_connect_error()); // http_response_code(500); // 内部服务器错误 echo "Error: Could not connect to the database."; exit;}
// 设置字符集(推荐)mysqli_set_charset($conn, 'utf8mb4');
// --- 准备 SQL 语句(安全!)---$sql = "SELECT FirstName, LastName, Age, Hometown, Job FROM users WHERE id = ?";$stmt = mysqli_prepare($conn, $sql);
if (!$stmt) { error_log("SQL Prepare Error: " . mysqli_error($conn)); echo "Error preparing database query."; mysqli_close($conn); exit;}
// --- 绑定参数并执行 ---mysqli_stmt_bind_param($stmt, "i", $userId); // 'i' 指定变量类型为整数
mysqli_stmt_execute($stmt);
// --- 获取结果 ---$result = mysqli_stmt_get_result($stmt);
// --- 构建 HTML 响应 ---if ($result && mysqli_num_rows($result) > 0) { echo "<table> <tr> <th>Firstname</th> <th>Lastname</th> <th>Age</th> <th>Hometown</th> <th>Job</th> </tr>";
while ($row = mysqli_fetch_assoc($result)) { echo "<tr>"; // 使用 htmlspecialchars 防止在 HTML 中回显数据时的 XSS 攻击 echo "<td>" . htmlspecialchars($row['FirstName'] ?? '', ENT_QUOTES, 'UTF-8') . "</td>"; echo "<td>" . htmlspecialchars($row['LastName'] ?? '', ENT_QUOTES, 'UTF-8') . "</td>"; echo "<td>" . htmlspecialchars((string)($row['Age'] ?? ''), ENT_QUOTES, 'UTF-8') . "</td>"; echo "<td>" . htmlspecialchars($row['Hometown'] ?? '', ENT_QUOTES, 'UTF-8') . "</td>"; echo "<td>" . htmlspecialchars($row['Job'] ?? '', ENT_QUOTES, 'UTF-8') . "</td>"; echo "</tr>"; } echo "</table>";} else if ($result) { echo "No user found with ID: " . htmlspecialchars((string)$userId, ENT_QUOTES, 'UTF-8');} else { error_log("SQL Execute Error: " . mysqli_stmt_error($stmt)); echo "Error retrieving user data.";}
// --- 清理 ---mysqli_stmt_close($stmt);mysqli_close($conn);
?>PHP 脚本讲解:
- 配置: 设置数据库凭据(应安全存储)。
- 输入验证:
filter_input()获取并将q参数验证为整数。 - 数据库连接: 使用
mysqli_connect()连接到 MySQL。错误处理至关重要。 - 字符集: 将连接字符集设置为
utf8mb4(推荐)。 - 预处理语句: 使用
mysqli_prepare()准备带有占位符(?)的 SQL 查询。 - 绑定参数: 使用
mysqli_stmt_bind_param()将验证后的$userId绑定到占位符。这是防止 SQL 注入的关键步骤。 - 执行: 使用
mysqli_stmt_execute()执行预处理语句。 - 获取结果:
mysqli_stmt_get_result()获取结果。 - 构建响应: 如果找到用户,则使用数据构建 HTML 表格。输出时使用
htmlspecialchars()确保安全。 - 错误处理: 在连接、准备和执行阶段检查错误。
- 清理: 使用
mysqli_stmt_close()和mysqli_close()关闭语句和连接。
本示例使用 MySQLi 过程式风格。您也可以使用 MySQLi 面向对象风格或 PDO(PHP Data Objects)实现相同功能,这两种方式也都强烈支持预处理语句。