You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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脚本优化

  1. 配置信息隔离
    将数据库连接参数($servername、$username、$password、$dbname)提取到单独的配置文件(如config.php),并将该配置文件放在Web根目录以外,或通过服务器配置禁止直接访问,避免敏感信息泄露。

  2. 统一错误处理与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();
    ?>
    
  3. 简化数组构造逻辑
    原代码中手动构造$player数组完全可以省略,直接将fetch_assoc()返回的数组推入$players即可,减少冗余代码。

JS脚本优化

  1. 使用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);
        });
    
  2. 防范XSS攻击
    原代码直接将用户数据插入innerHTML存在XSS风险,改用textContent赋值文本内容,确保用户输入的恶意代码不会被执行。

  3. 增强用户反馈
    增加加载状态提示、空数据提示和错误提示,提升用户体验,让用户清楚当前数据加载状态。

内容的提问来源于stack exchange,提问作者bragi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 17:17:52