WordPress PHP插件被JS调用时显示成功但未更新数据库
问题:AJAX调用WordPress插件脚本无法更新数据库,直接访问却正常
我搭建了WordPress站点,开发了一个插件用来更新自定义数据库,目的是限制用户使用工具的次数。数据库包含用户ID和使用次数列,检查次数阈值的功能正常,但遇到了奇怪的问题:
- 直接在浏览器访问插件的PHP链接时,能成功获取用户ID并更新数据库;
- 用HTML/JS的fetch调用这个脚本时,控制台显示调用成功,但数据库根本没更新。
插件PHP代码
<?php /* Plugin Name: Track User Usage Plugin URL: REDACTED Description: Version: 1.0 Author: REDACTED */ define('DB_SERVER2', 'REDACTED'); define('DB_USERNAME2', 'REDACTED'); define('DB_PASSWORD2', 'REDACTED'); define('DB_NAME2', 'REDACTED'); // Establish a persistent database connection $conn = new mysqli(DB_SERVER2, DB_USERNAME2, DB_PASSWORD2, DB_NAME2); $conn->autocommit(TRUE); $conn->real_query("SET NAMES 'utf8'"); // Checking connection if ($conn->connect_error) { die('Database connection failed: ' . $conn->connect_error); } function process_request() { global $conn; if ( ! defined( 'ABSPATH' ) ) { define( 'ABSPATH', '/home/REDACTED/REDACTED.com/' ); } if ($_SERVER['REQUEST_METHOD'] !== 'GET') { return; } include_once ABSPATH . '/wp-load.php'; $userid = get_current_user_id(); if ($userid == 0) { return; } $user_id = $userid; $created_at = date('Y-m-d H:i:s'); // Check if the user already exists in the table $sql_check_user = "SELECT * FROM tool_usage WHERE user_id = ?"; $stmt_check_user = $conn->prepare($sql_check_user); $stmt_check_user->bind_param("i", $user_id); $stmt_check_user->execute(); $result = $stmt_check_user->get_result(); if ($result->num_rows > 0) { // User exists, update the usage count $sql_update_usage = "UPDATE tool_usage SET usage_count = usage_count + 1 WHERE user_id = ?"; $stmt_update_usage = $conn->prepare($sql_update_usage); $stmt_update_usage->bind_param("i", $user_id); if ($stmt_update_usage->execute()) { } else { } } else { // User doesn't exist, insert a new record $usage_count = 1; // Initial usage count $sql_insert = "INSERT INTO tool_usage (user_id, usage_count, created_at) VALUES (?, ?, ?)"; $stmt_insert = $conn->prepare($sql_insert); $stmt_insert->bind_param("iis", $user_id, $usage_count, $created_at); if ($stmt_insert->execute()) { } else { } } $stmt_check_user->close(); } process_request(); $conn->close(); ?>
注:部分else语句为空,是因为原来的echo语句引发问题,我删掉了,原本用来输出成功信息。
测试HTML/JS代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Track User Usage</title> <script> function trackUserUsage() { fetch('https://www.REDACTED.com/wp-content/plugins/track_user_usage/track_user_usage.php') .then(data => { if (data.success) { console.log('PHP script called successfully:', data); } else { console.error('PHP script error:', data); } }) .catch(error => { console.error('Error calling PHP script:', error); }); } </script> </head> <body> <button onclick="trackUserUsage()">Track User Usage</button> </body> </html>
问题排查与修复方案
核心原因
直接访问PHP脚本时,浏览器自动携带了WordPress的会话Cookie,所以get_current_user_id()能拿到正确的用户ID;但fetch请求默认不发送Cookie,导致get_current_user_id()返回0,脚本直接执行return,跳过了数据库更新逻辑。
具体修复步骤
1. 修改JS的fetch请求,强制携带Cookie
在fetch的配置里加上credentials: 'include',确保请求发送当前域名的会话Cookie:
function trackUserUsage() { fetch('https://www.REDACTED.com/wp-content/plugins/track_user_usage/track_user_usage.php', { credentials: 'include' // 关键:带上Cookie以保持用户登录状态 }) .then(response => response.text()) // 先解析响应内容(如果PHP返回JSON就用response.json()) .then(result => { console.log('请求响应:', result); }) .catch(error => { console.error('请求失败:', error); }); }
注意:原来的data.success是错误写法,fetch返回的是Response对象,必须先解析成文本或JSON才能读取内容。
2. 优化PHP脚本的调试与安全性
- 添加错误日志:在
$userid == 0时记录日志,方便确认是否是用户身份问题:if ($userid == 0) { error_log('Track Usage Plugin: 未检测到已登录用户'); return; } - 输出响应结果:在数据库操作后返回明确的状态,方便前端判断:
对应的前端可以改成解析JSON:// 更新成功后添加 echo json_encode(['success' => true, 'message' => '使用次数更新成功', 'user_id' => $user_id]); // 失败时添加 echo json_encode(['success' => false, 'message' => '更新失败', 'error' => $stmt_update_usage->error]);.then(response => response.json()) .then(data => { if (data.success) { console.log('跟踪成功:', data); } else { console.error('跟踪失败:', data.error); } }) - 改用WordPress原生数据库连接:插件里没必要自己新建mysqli连接,可以直接用WordPress的
$wpdb类,避免硬编码数据库信息和路径问题:// 替换原有的数据库连接代码,直接使用$wpdb global $wpdb; // 查询示例: $result = $wpdb->get_row($wpdb->prepare("SELECT * FROM tool_usage WHERE user_id = %d", $user_id));
3. 处理跨域问题(如果测试页面不在同一域名)
如果测试HTML是在其他域名下打开的,需要在PHP脚本开头添加CORS响应头:
// 允许指定域名的跨域请求,替换成你的测试域名 header("Access-Control-Allow-Origin: https://your-test-domain.com"); header("Access-Control-Allow-Credentials: true");
注意:不能用*作为Access-Control-Allow-Origin,否则无法携带Cookie。
内容的提问来源于stack exchange,提问作者user25236328
相关产品推荐
相关产品推荐

