JS调用fetch_data.php返回404,求问题排查及方案优化建议
404错误排查与实现方案优化建议
一、404错误排查步骤
- 文件名与路径验证:确认
fetch_data.php文件名完全匹配(注意Linux服务器区分大小写),且和HTML文件在同一Web目录下。直接在浏览器地址栏输入http://www.<website>.com/fetch_data.php,检查是否能正常访问。 - 服务器PHP解析配置:确认Web服务器(Apache/Nginx等)已启用PHP解析功能,比如Apache需开启
mod_php模块,Nginx需配置PHP-FPM转发规则,避免PHP文件被当作静态文件返回或拦截。 - 文件权限检查:确保
fetch_data.php的文件权限设置为服务器进程可读取(推荐644权限),避免因权限不足导致服务器无法访问该文件。
二、实现方案优化建议
PHP脚本优化
配置信息隔离
将数据库连接参数($servername、$username、$password、$dbname)提取到单独的配置文件(如config.php),并将该配置文件放在Web根目录以外,或通过服务器配置禁止直接访问,避免敏感信息泄露。统一错误处理与JSON输出
当前错误输出和空结果返回格式不统一,容易导致JS解析失败,同时生产环境不要暴露明文错误信息:<?php // 引入配置文件 require_once 'config.php'; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { // 记录错误到服务器日志 error_log("DB Connection failed: " . $conn->connect_error); header("HTTP/1.1 500 Internal Server Error"); header('Content-Type: application/json'); echo json_encode(["error" => "服务器内部错误"]); exit; } $sql = "SELECT name, description, hcp, image FROM players"; $result = $conn->query($sql); header('Content-Type: application/json'); if ($result->num_rows > 0) { $players = []; while ($row = $result->fetch_assoc()) { $players[] = $row; // 直接复用查询结果,无需重新构造数组 } echo json_encode(["players" => $players]); } else { echo json_encode(["players" => []]); } $conn->close(); ?>简化数组构造逻辑
原代码中手动构造$player数组完全可以省略,直接将fetch_assoc()返回的数组推入$players即可,减少冗余代码。
JS脚本优化
使用Fetch API替代XMLHttpRequest
Fetch API基于Promise,代码更简洁易读,支持异步/await写法:const gridContainer = document.querySelector(".grid-container"); // 显示加载状态 gridContainer.innerHTML = '<div class="loading">加载中...</div>'; fetch('./fetch_data.php') .then(response => { if (!response.ok) throw new Error(`请求失败: ${response.status}`); return response.json(); }) .then(data => { gridContainer.innerHTML = ''; // 清空加载提示 if (data.players.length === 0) { gridContainer.innerHTML = '<p>暂无球员数据</p>'; return; } data.players.forEach(player => { const gridItem = document.createElement("div"); gridItem.classList.add("grid-item"); // 用文本节点赋值避免XSS const topWrapper = document.createElement('div'); topWrapper.classList.add('top-wrapper'); const imgWrapper = document.createElement('div'); imgWrapper.classList.add('img-wrapper'); const img = document.createElement('img'); img.src = `pics/${player.image}`; img.alt = player.name; imgWrapper.appendChild(img); const infoWrapper = document.createElement('div'); infoWrapper.classList.add('info-wrapper'); const nameH2 = document.createElement('h2'); nameH2.textContent = player.name; const descP = document.createElement('p'); descP.textContent = player.description; infoWrapper.append(nameH2, descP); topWrapper.append(imgWrapper, infoWrapper); const statsWrapper = document.createElement('div'); statsWrapper.classList.add('stats-wrapper'); const statsItem = document.createElement('div'); statsItem.classList.add('stats-item'); const hcpH3 = document.createElement('h3'); hcpH3.textContent = 'HCP'; const hcpP = document.createElement('p'); hcpP.textContent = `#${player.hcp}`; statsItem.append(hcpH3, hcpP); statsWrapper.appendChild(statsItem); const inputWrapper = document.createElement('div'); inputWrapper.classList.add('input-wrapper'); const input = document.createElement('input'); input.type = 'text'; input.placeholder = '???'; const btn = document.createElement('button'); btn.classList.add('input-btn'); const icon = document.createElement('i'); icon.classList.add('fa-solid', 'fa-paper-plane'); btn.appendChild(icon); inputWrapper.append(input, btn); gridItem.append(topWrapper, statsWrapper, inputWrapper); gridContainer.appendChild(gridItem); }); }) .catch(error => { gridContainer.innerHTML = `<p>数据加载失败: ${error.message}</p>`; console.error(error); });防范XSS攻击
原代码直接将用户数据插入innerHTML存在XSS风险,改用textContent赋值文本内容,确保用户输入的恶意代码不会被执行。增强用户反馈
增加加载状态提示、空数据提示和错误提示,提升用户体验,让用户清楚当前数据加载状态。
内容的提问来源于stack exchange,提问作者bragi
相关产品推荐
相关产品推荐

