PHP中json_encode异常行为:带单引号消息的Firebase推送问题
解决带单引号消息的json_encode异常问题
我之前也踩过这个一模一样的坑!问题的核心在于addslashes()的转义逻辑和JSON的序列化规则完全不兼容,直接导致json_encode罢工。
为什么会出问题?
addslashes()是给单引号这类特殊字符加反斜杠(比如把'变成\'),目的是适配SQL语句的字符串格式,防止注入。但JSON的字符串规则里,单引号本身不需要转义(JSON用双引号包裹字符串),而且addslashes()加的反斜杠会被json_encode当成无效的非法转义字符,要么返回false,要么生成一堆不符合规范的JSON,Firebase自然没法正确解析。
两种解决方案,按需选择:
1. 最佳实践:放弃手动转义,用数据库参数绑定
这是一劳永逸的办法,既彻底解决SQL注入风险,又能完全避免转义带来的后续麻烦。以PDO为例:
// 假设你用PDO连接数据库 $pdo = new PDO('mysql:host=localhost;dbname=your_db', 'db_user', 'db_pass'); // 用占位符写预处理SQL,不用手动拼接变量 $stmt = $pdo->prepare("INSERT INTO messages (sender_id, receiver_id, content) VALUES (:sender, :receiver, :content)"); // 直接绑定原始消息,PDO会自动处理所有转义逻辑 $stmt->bindParam(':sender', $senderId); $stmt->bindParam(':receiver', $receiverId); $stmt->bindParam(':content', $originalMessage); // 比如直接传"This message doesn't work" $stmt->execute();
这样存入数据库的是原始字符串(数据库会自己处理内部单引号的存储),后续取出来直接丢给json_encode序列化就完全没问题。
2. 临时方案:如果暂时没法改数据库存储逻辑
如果已经用addslashes()存了数据,那在json_encode之前必须先还原成原始字符串:
// 从数据库取出的、经过addslashes处理的字符串 $dbMessage = "This message doesn\\'t work"; // 去掉addslashes添加的多余反斜杠 $originalMessage = stripslashes($dbMessage); // 再进行JSON序列化,json_encode会按照JSON规则自动处理转义 $payload = json_encode([ 'to' => '/topics/user_2', 'notification' => [ 'title' => '新消息', 'body' => $originalMessage ] ]); // 别忘了加个调试判断,方便定位问题 if ($payload === false) { error_log("JSON编码失败: " . json_last_error_msg()); } // 最后用curl请求Firebase $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: key=你的FCM密钥', 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); curl_exec($ch); curl_close($ch);
这里stripslashes()会把\\'还原成',让json_encode能正确识别字符串内容,生成符合规范的JSON数据。
额外调试小技巧
如果还是遇到json_encode失败,用这两行代码快速定位错误:
$json = json_encode($yourData); if ($json === false) { echo "JSON编码错误详情: " . json_last_error_msg(); }
能帮你快速搞清楚是转义问题还是其他格式问题。
内容的提问来源于stack exchange,提问作者Harvey Fletcher
相关产品推荐
相关产品推荐

