Ajax结合PHP MySQL加载图片模态框数据报错问题排查
缩略图点击加载详情接口报错修复
问题描述
- 需求:点击缩略图弹出大图,同时异步加载对应图片的详情内容展示在图片旁
- 实现逻辑:点击缩略图时触发绑定函数,从DOM的dataset属性读取图片ID,将ID传入PHP接口查询MySQL数据库,返回对应描述内容渲染到模态框
- 异常:原生JS、jQuery两个版本的实现均无法正常加载内容,页面返回PHP报错信息
运行时抛出的报错:
Warning: Undefined array key "datapass" in C:\xampp\htdocs\Project\modalTitle.php on line 3 Fatal error: Uncaught TypeError: mysqli_fetch_all(): Argument #1 ($result) must be of type mysqli_result, bool given in C:\xampp\htdocs\Project\modalTitle.php:9 Stack trace: #0 C:\xampp\htdocs\Project\modalTitle.php(9): mysqli_fetch_all(false, 1) #1 {main} thrown in C:\xampp\htdocs\Project\modalTitle.php on line 9
问题根因
- 原生JS版本的XHR请求未拼接
datapass参数,请求地址只有modalTitle.php,没有携带图片ID,PHP端读取不到$_GET['datapass']触发第一个警告 - PHP端无入参校验逻辑,参数缺失时直接拼接到SQL语句,生成的SQL语法错误(
SELECT description FROM content where timecode=),mysqli_query执行失败返回false,将布尔值传入mysqli_fetch_all触发第二个致命错误 - 原PHP代码直接拼接用户传入参数到SQL语句,存在SQL注入风险
- 前端无异常处理逻辑,接口报错时直接将错误信息渲染到页面
修复后代码
原生JS版本
function modalTitleLoad(e) { // 兼容点击缩略图内部子元素的场景,向上查找绑定data-id的DOM节点 const target = e.target.closest('[data-id]'); if (!target) return; const imgId = target.dataset.id; const xhr = new XMLHttpRequest(); // GET请求参数拼接在URL后,使用encodeURIComponent处理特殊字符 xhr.open('GET', `modalTitle.php?datapass=${encodeURIComponent(imgId)}`); xhr.onload = function () { const titleDom = document.querySelector('.modal__title'); if (this.status !== 200) { titleDom.textContent = '加载失败,请重试'; return; } try { const res = JSON.parse(this.response); titleDom.textContent = res.code === 0 ? (res.data.description || '暂无详情') : (res.msg || '加载失败'); } catch (err) { titleDom.textContent = '数据解析失败'; } }; xhr.onerror = function () { document.querySelector('.modal__title').textContent = '网络异常,请检查连接'; }; xhr.send(); } // 绑定点击事件示例:document.querySelectorAll('.thumbnail').forEach(item => item.addEventListener('click', modalTitleLoad))
jQuery版本
function modalData(e) { const target = e.target.closest('[data-id]'); if (!target) return; const imgId = target.dataset.id; $.ajax({ type: 'GET', url: 'modalTitle.php', dataType: 'json', // 自动解析JSON格式返回值 data: { datapass: imgId }, success: function (res) { $('.modal__title').text(res.code === 0 ? (res.data.description || '暂无详情') : (res.msg || '加载失败')); }, error: function () { $('.modal__title').text('请求失败,请重试'); } }); } // 不要手动全局调用modalData(event),通过事件绑定自动传入事件对象 // 绑定示例:$('.thumbnail').on('click', modalData)
PHP接口版本
<?php header('Content-Type: application/json; charset=utf-8'); // 统一返回结构 $res = ['code' => 1, 'msg' => '参数非法', 'data' => null]; // 入参校验 if (!isset($_GET['datapass']) || !trim($_GET['datapass'])) { echo json_encode($res); exit; } $imgId = trim($_GET['datapass']); // 数据库连接校验 $conn = mysqli_connect('localhost', 'root', '', 'db'); if (!$conn) { $res['msg'] = '服务异常'; echo json_encode($res); exit; } mysqli_set_charset($conn, 'utf8mb4'); // 预处理语句防SQL注入,若timecode是数字类型将bind_param的第一个参数's'改为'i' $stmt = mysqli_prepare($conn, "SELECT description FROM content WHERE timecode = ?"); mysqli_stmt_bind_param($stmt, "s", $imgId); mysqli_stmt_execute($stmt); $queryRes = mysqli_stmt_get_result($stmt); if (!$queryRes) { $res['msg'] = '查询失败'; echo json_encode($res); exit; } $row = mysqli_fetch_assoc($queryRes); if ($row) { $res['code'] = 0; $res['msg'] = 'success'; $res['data'] = $row; } else { $res['msg'] = '未查询到对应内容'; } echo json_encode($res); // 释放资源 mysqli_stmt_close($stmt); mysqli_close($conn); ?>
内容的提问来源于stack exchange,提问作者Javashift
相关产品推荐
相关产品推荐

