条件判断失效问题:基于条件发送FCM通知的函数开发异常
解决FCM通知条件判断失效问题
看起来你在开发基于条件触发FCM通知的功能时遇到了条件判断失效的问题,我来帮你梳理下代码里的几个关键问题并给出修复方案:
首先先把你的原始代码片段贴出来方便分析:
$number = $_GET["number"]; $status = $_GET["status"]; $userIds = $_GET["userId"]; $sql = ""; for($i = 0; $i < count($number); $i++) { $sql .= "INSERT INTO number_status (number, number_status, user_id) VALUES ('$number[$i]', $status[$i], $userIds[$i]);"; if($status[$i] == 1) { $sqlSelect = "SELECT t2.name, t1.fcm, t1.fcm_enabled FROM user AS t1 INNER JOIN number_list AS t2 ON t1.id = t2.user_id WHERE ..."; } }
问题分析
- SQL注入高危风险:直接将
$_GET参数拼接进SQL语句,这会导致严重的安全漏洞,恶意用户可以通过构造参数篡改你的数据库操作。 - 循环内变量覆盖问题:每次循环中如果
status[$i] == 1,$sqlSelect都会被重新赋值,最终你只能得到最后一次满足条件的查询语句,之前的都会被覆盖,这会导致你无法收集所有需要发送FCM通知的用户。 - 松散相等的潜在bug:
$status[$i]是从$_GET获取的字符串类型,使用== 1会触发PHP的松散类型转换,可能导致非预期的判断结果(比如字符串"01"也可能被误判为等于1),应该使用严格相等=== 1,或者先将$status[$i]转换为整数。 - 不完整的查询语句:
$sqlSelect中的WHERE ...部分是缺失的,这会导致SQL执行失败,自然无法获取到需要发送通知的用户信息,进而让FCM通知逻辑无法正常工作。 - 未验证输入合法性:没有检查
$number、$status、$userIds是否为数组,以及三个数组的长度是否一致,这会导致循环时出现索引越界的错误。
修复后的代码示例
// 先验证输入的合法性 if (!is_array($_GET["number"]) || !is_array($_GET["status"]) || !is_array($_GET["userId"])) { die("Invalid input parameters"); } $number = $_GET["number"]; $status = $_GET["status"]; $userIds = $_GET["userId"]; // 检查三个数组长度是否一致 if (count($number) !== count($status) || count($number) !== count($userIds)) { die("Input arrays must have the same length"); } // 使用PDO预处理语句避免SQL注入 $pdo = new PDO("mysql:host=your_host;dbname=your_db", "username", "password"); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 准备插入语句 $insertStmt = $pdo->prepare("INSERT INTO number_status (number, number_status, user_id) VALUES (?, ?, ?)"); // 收集需要发送FCM通知的用户信息 $fcUsers = []; for($i = 0; $i < count($number); $i++) { // 严格判断status是否为1(先转整数确保类型正确) $currentStatus = (int)$status[$i]; // 执行插入操作 $insertStmt->execute([$number[$i], $currentStatus, $userIds[$i]]); if($currentStatus === 1) { // 完善WHERE条件,这里示例根据user_id和number筛选目标用户 $selectStmt = $pdo->prepare(" SELECT t2.name, t1.fcm, t1.fcm_enabled FROM user AS t1 INNER JOIN number_list AS t2 ON t1.id = t2.user_id WHERE t1.id = ? AND t2.number = ? "); $selectStmt->execute([$userIds[$i], $number[$i]]); $user = $selectStmt->fetch(PDO::FETCH_ASSOC); if ($user && !empty($user['fcm']) && $user['fcm_enabled']) { $fcUsers[] = $user; } } } // 现在可以遍历$fcUsers发送FCM通知 foreach ($fcUsers as $user) { // 这里编写你的FCM通知发送逻辑 // sendFCMNotification($user['fcm'], $user['name']); }
额外提示
- 永远不要信任用户输入,必须使用预处理语句(PDO或mysqli_stmt)来防止SQL注入。
- 对于FCM通知,确保你已经正确集成了FCM SDK,并且用户的
fcm令牌是有效的,fcm_enabled状态为开启。 - 可以添加try-catch错误捕获逻辑包裹数据库操作,方便排查执行过程中的问题。
内容的提问来源于stack exchange,提问作者Khushi Patel
相关产品推荐
相关产品推荐

