
本文详解 AJAX 与 PHP 协同获取数据库数据时的常见问题:前端能收到响应但无法显示真实数据库内容,根源在于数据格式不匹配、JSON 处理缺失及 SQL 注入风险。解决方案包括统一使用 JSON 通信、正确解析响应、修复 AJAX 配置,并增强安全性。
本文详解 ajax 与 php 协同获取数据库查询结果时的常见问题:前端能收到响应但无法显示真实数据库内容,根源在于数据格式不匹配、json 处理缺失及 sql 注入风险。解决方案包括统一使用 json 通信、正确解析响应、修复 ajax 配置,并增强安全性。
在使用 AJAX 异步加载数据库内容时,一个典型误区是:PHP 脚本能成功执行(如输出 echo "test"),却无法返回预期的数据库字段值(如只显示 "pizza" 而非数据库中 name 字段的真实值)。这并非数据库连接失败,而是前后端数据协议不一致导致的——当前代码混合了原始 HTML 输出、手动解析请求体、未设置响应头,且存在严重安全漏洞。
✅ 正确做法:前后端统一采用 JSON 格式通信
1. 修正 PHP 端(php/recipe-container.php)
- 移除手动解析
php://input(substr(..., 9, -2)极其脆弱且不可靠); - 使用
$_POST接收数据(因 AJAX 已设processData: false,但实际应启用processData: true并发送标准表单数据); - 启用错误报告与数据库连接检查;
-
关键:使用
json_encode()输出结构化数据,并设置Content-Type: application/json; - 防止 SQL 注入:必须使用预处理语句(
mysqli_prepare)。
<?php
header('Content-Type: application/json; charset=utf-8');
function display($product) {
$con = mysqli_connect("localhost", "root", "", "cookbook");
if (!$con) {
return ['error' => 'Database connection failed'];
}
// ✅ 使用预处理语句防止 SQL 注入
$stmt = mysqli_prepare($con, "SELECT name, description, date FROM product WHERE name = ?");
if (!$stmt) {
return ['error' => 'Prepare failed: ' . mysqli_error($con)];
}
mysqli_stmt_bind_param($stmt, "s", $product);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$data = [];
if (mysqli_num_rows($result) > 0) {
while ($row = mysqli_fetch_assoc($result)) {
$data[] = $row; // 支持多条记录(如重名场景)
}
} else {
$data = ['message' => 'No product found'];
}
mysqli_stmt_close($stmt);
mysqli_close($con);
return $data;
}
// ✅ 使用 $_POST 获取数据(更可靠、更标准)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['data'])) {
echo json_encode(display($_POST['data']));
exit;
}
?>2. 修正 JavaScript 端(AJAX 配置)
- 删除重复的
processData: false; -
启用
processData: true和contentType: 'application/x-www-form-urlencoded'(默认值),让 jQuery 自动序列化数据; - 在
success回调中解析 JSON 响应,并安全渲染 DOM(避免 XSS); - 添加错误处理逻辑。
$(function () {
$('.product').on('click', function (e) {
const product = $(this).attr('id');
$.ajax({
type: "POST",
url: 'php/recipe-container.php',
data: { data: product }, // ✅ 简洁、安全、自动编码
dataType: 'json', // ✅ 明确期望 JSON 响应
success: function(response) {
if (response.error) {
$(".display_recipe").html(`<div class="error">Error: ${response.error}</div>`);
return;
}
if (Array.isArray(response) && response.length > 0) {
const html = response.map(item => `
<div class="recipe-item">
<h3>${escapeHtml(item.name)}</h3>
<p><strong>Description:</strong> ${escapeHtml(item.description)}</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill2138" title="PHP"><img
src="https://img.php.cn/upload/skill/000/000/081/178884013267959.jpg" alt="PHP" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill2138" title="PHP">PHP</a>
<p>编写健壮的PHP代码,规避类型转换陷阱、数组怪癖及常见安全漏洞。</p>
</div>
<a href="/xiazai/skill2138" title="PHP" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div>
<small><em>Added on: ${escapeHtml(item.date)}</em></small>
</div>
`).join('');
$(".display_recipe").html(html);
} else {
$(".display_recipe").html(`<div class="info">${response.message || 'No data returned.'}</div>`);
}
},
error: function(xhr, status, err) {
$(".display_recipe").html(`<div class="error">AJAX Error: ${status} — ${err}</div>`);
}
});
});
});
// 辅助函数:防止 XSS
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}⚠️ 注意事项与最佳实践
-
永远不要拼接用户输入到 SQL 查询中:原代码
$sql = "SELECT * ... '$product'"是高危 SQL 注入入口,必须替换为预处理语句。 -
避免
file_get_contents("php://input")解析 POST 数据:它适用于application/json请求体,但当前 AJAX 并未发送 JSON,且手动截取字符串极易出错(如substr(...,9,-2)依赖特定 JSON 结构,极不稳定)。 -
HTML 中的
<?php require ... ?>是冗余且有害的:页面首次加载时会执行一次 PHP,但此时$_POST为空,可能报错或输出空内容;应完全由 AJAX 动态加载,移除该require行。 -
始终验证和清理输出:使用
escapeHtml()或服务端模板引擎转义内容,防止 XSS 攻击。 -
开启错误报告用于开发(生产环境关闭):
error_reporting(E_ALL); ini_set('display_errors', 1);
通过以上重构,AJAX 将稳定接收结构化 JSON 数据,前端可精准提取字段并安全渲染,彻底解决“只显示 ID 名称而非数据库内容”的问题,同时大幅提升代码健壮性与安全性。


















