如何每日定时自动向PHP脚本发起AJAX请求?执行失败求助
排查每日信用值添加失败的问题
看起来你遇到的问题可能出在前端定时可靠性、后端逻辑漏洞或者用户身份识别这几个环节上,我帮你一步步拆解排查:
一、先解决最核心的问题:前端定时不可靠
你现在用前端AJAX定时的最大问题是:用户必须在23点时保持浏览器打开且页面处于活跃状态,只要用户关了页面、浏览器,或者页面被后台挂起,请求就不会触发。这显然不符合“每位用户每日自动获得信用”的需求。
正确的做法:改用后端定时任务(推荐)
后端定时任务完全不依赖用户操作,到点自动执行,这才是批量更新用户信用的靠谱方案:
1. 编写批量更新的PHP脚本(比如daily_credit_sync.php)
<?php // 连接数据库(以PDO为例,确保配置正确) $dsn = 'mysql:host=localhost;dbname=你的数据库名;charset=utf8mb4'; $db_user = '数据库用户名'; $db_pass = '数据库密码'; try { $pdo = new PDO($dsn, $db_user, $db_pass); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 批量给所有用户添加5信用(如果需要排除禁用用户,可加WHERE条件) $stmt = $pdo->prepare("UPDATE users SET Credit = Credit + 5"); $stmt->execute(); // 记录执行日志,方便排查 error_log(date('Y-m-d H:i:s') . " 成功为 {$stmt->rowCount()} 位用户添加5信用"); } catch (PDOException $e) { error_log(date('Y-m-d H:i:s') . " 信用更新失败:" . $e->getMessage()); } ?>
2. 配置服务器定时任务(Cron)
如果是Linux服务器,运行crontab -e添加一行:
0 23 * * * php /你的脚本绝对路径/daily_credit_sync.php
这行代码的意思是:每天23点0分自动执行这个PHP脚本,批量更新所有用户的信用值。
二、如果坚持用前端方案(仅适合用户必须在线的场景)
先排查前端代码的问题:
1. 确保定时器逻辑正确
你需要计算当前时间到23点的时间差,而不是固定间隔,否则可能出现时间偏差。示例代码:
function scheduleCreditUpdate() { const now = new Date(); let target = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 0, 0); // 如果当前时间已过23点,就设置到第二天的23点 if (now > target) { target.setDate(target.getDate() + 1); } const delay = target.getTime() - now.getTime(); setTimeout(() => { // 发起AJAX请求,必须带上用户会话凭证 fetch('addCredits.php', { method: 'POST', credentials: 'include' // 关键:带上Cookie,让后端识别当前用户 }) .then(res => res.text()) .then(data => console.log('信用更新结果:', data)) .catch(err => console.error('请求失败:', err)); // 递归调用,实现每日循环 scheduleCreditUpdate(); }, delay); } // 启动定时任务 scheduleCreditUpdate();
2. 排查后端addCredits.php的问题
后端必须正确识别用户,且SQL语句无错误:
<?php session_start(); // 第一步:验证用户是否登录 if (!isset($_SESSION['user_id'])) { error_log('未登录用户尝试更新信用'); http_response_code(401); exit('请先登录'); } $user_id = $_SESSION['user_id']; // 第二步:执行安全的SQL更新(用参数化查询防注入) $dsn = 'mysql:host=localhost;dbname=你的数据库名;charset=utf8mb4'; $db_user = '数据库用户名'; $db_pass = '数据库密码'; try { $pdo = new PDO($dsn, $db_user, $db_pass); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $pdo->prepare("UPDATE users SET Credit = Credit + 5 WHERE id = :user_id"); $stmt->bindParam(':user_id', $user_id, PDO::PARAM_INT); $stmt->execute(); if ($stmt->rowCount() > 0) { echo '信用已添加'; error_log("用户ID {$user_id} 成功获得5信用"); } else { echo '无用户匹配或无需更新'; } } catch (PDOException $e) { error_log('信用更新数据库错误:' . $e->getMessage()); http_response_code(500); echo '服务器内部错误'; } ?>
三、快速排查步骤
- 直接测试后端:用Postman或curl发送POST请求到
addCredits.php(带上登录后的Cookie),看数据库中对应用户的Credit是否增加,同时查看服务器错误日志(比如Apache/Nginx的error_log)。 - 检查前端控制台:23点前后打开浏览器开发者工具,看Network面板是否有请求发送,Console面板是否有报错(比如跨域、401未授权等)。
- 优先切换到后端定时:前端定时本质上是依赖用户在线,这在生产环境中几乎不可靠,后端定时才是正确的解决方案。
内容的提问来源于stack exchange,提问作者Lili
相关产品推荐
相关产品推荐

