PHP无法直接绑定用户播放偏好,仅负责接收校验并存储前端传来的playback_rate等白名单字段为JSON,存入UTF-8mb4兼容的TEXT字段,并通过API返回标准JSON响应。

PHP 调用听书插件时,无法直接“绑定用户播放偏好”,因为偏好数据必须由前端或客户端采集(如播放速度、默认音源、章节记忆点、是否自动续播),PHP 仅负责接收、校验、持久化这些值——关键在于「谁传、怎么传、存哪、怎么读」。
如何通过 PHP 接收并存储用户播放偏好
听书插件(如基于 Web Audio 或第三方 SDK)通常在用户操作后通过 fetch 或 XMLHttpRequest 向 PHP 接口提交偏好数据。PHP 端需提供一个接收接口(如 /api/save_preference.php),并完成基础校验与写入。
- 必须校验
$_POST['user_id']或登录态(如从$_SESSION['uid']获取),禁止信任前端传来的任意user_id - 偏好字段应白名单过滤:只允许保存
playback_rate、default_source、last_chapter_id、auto_resume等已知键名 - 推荐用
json_encode()存入数据库单字段(如user_preferencesTEXT),而非拆成多列——便于扩展新偏好项 - 若用 MySQL,确保该字段支持 UTF-8mb4 编码,避免 emoji 或特殊音源名入库失败
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit('Method not allowed');
}
$user_id = $_SESSION['uid'] ?? 0;
if (!$user_id) {
http_response_code(401);
exit('Unauthorized');
}
$allowed_keys = ['playback_rate', 'default_source', 'last_chapter_id', 'auto_resume'];
$preference = [];
foreach ($_POST as $k => $v) {
if (in_array($k, $allowed_keys)) {
$preference[$k] = is_scalar($v) ? trim((string)$v) : null;
}
}
$json = json_encode($preference, JSON_UNESCAPED_UNICODE);
// 执行 INSERT ON DUPLICATE KEY UPDATE 或 REPLACE INTO
$stmt = $pdo->prepare("INSERT INTO user_settings (user_id, preferences, updated_at) VALUES (?, ?, NOW()) ON DUPLICATE KEY UPDATE preferences = VALUES(preferences), updated_at = NOW()");
$stmt->execute([$user_id, $json]);
PHP 如何在响应听书插件请求时返回对应偏好
插件初始化时会请求用户当前偏好(如 /api/get_preference.php),PHP 需读取并输出合法 JSON,且设置正确 Header。
- 务必设置
Content-Type: application/json; charset=utf-8,否则前端JSON.parse()可能因 BOM 或编码错乱失败 - 空偏好不能返回
null或空字符串,应返回标准空对象{} - 敏感字段(如设备指纹、token)绝不可从
user_preferences字段中透出 - 若偏好含时间戳类字段(如
last_played_at),PHP 应统一转为秒级 Unix 时间戳,避免前端解析差异
header('Content-Type: application/json; charset=utf-8');
$user_id = $_SESSION['uid'] ?? 0;
if (!$user_id) {
echo json_encode([], JSON_UNESCAPED_UNICODE);
exit;
}
$stmt = $pdo->prepare("SELECT preferences FROM user_settings WHERE user_id = ?");
$stmt->execute([$user_id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
echo json_encode($row['preferences'] ?? [], JSON_UNESCAPED_UNICODE);
常见踩坑:前端传参格式与 PHP 解析不一致
听书插件常使用 FormData 或 application/json 提交,但 PHP 默认只解析 application/x-www-form-urlencoded 和 multipart/form-data 的 $_POST。若前端用 fetch('/save', {method:'POST', body:JSON.stringify(...)}),PHP 不会自动填充 $_POST。
立即学习“PHP免费学习笔记(深入)”;
- 前端发 JSON 时,PHP 需手动读取
php://input并json_decode(file_get_contents('php://input'), true) - 若插件同时支持多种提交方式(如表单 + JSON),建议统一入口:先判断
$_SERVER['CONTENT_TYPE']是否含application/json,再分支解析 -
playback_rate值为"1.25"字符串时,PHP 存库前应(float)强转,避免后续比较出错(如"1.25" > "1.5"字符串比较结果为 true) - MySQL 中若用
JSON类型字段(5.7+),注意 PHPjson_encode()输出的 JSON 必须严格合法,否则JSON_VALID()校验失败
真正难的不是存和取,而是「偏好」在多端(Web / App / 小程序)间的一致性同步。PHP 层没有状态,它只忠实地按约定读写;一旦前端漏传、缓存未更新、或用户登出后偏好未清理,整个链路就会断裂。别迷信“绑定”这个词——你绑定的只是数据库里一行记录,而用户的实际体验,取决于每一处读写是否都严守这个契约。











