Laravel集成Firebase推送报错:registration_ids字段不能为空
解决FCM推送时'registration_ids'字段为空的问题
我来帮你一步步排查这个问题,遇到'registration_ids' field cannot be empty的错误,本质上就是后端获取到的设备Token数组是空的,咱们从几个关键点入手解决:
1. 先确认设备Token是否真的成功保存到数据库
这是最核心的第一步,没有保存Token自然拿不到:
- 检查你的
User表是否存在device_token字段,类型建议设为varchar(255)(FCM Token长度大概在150字符左右),确保字段没有被误命名成其他(比如deviceToken)。 - 在后端的
saveToken方法里加个日志,确认是否收到了前端传过来的Token:use Illuminate\Support\Facades\Log; public function saveToken(Request $request) { Log::info('Received FCM Token: ' . $request->token); // 日志会存在storage/logs/laravel.log里 if(auth()->check()){ // 先确认用户已登录 auth()->user()->update(['device_token'=>$request->token]); return response()->json(['message' => 'Token saved successfully.']); } return response()->json(['message' => 'User not logged in.'], 401); } - 前端调用
initFirebaseMessagingRegistration时,用户必须处于登录状态!如果用户未登录,auth()->user()是null,根本不会更新数据库的Token。
2. 检查后端获取Token的逻辑
在sendNotification方法里,先确认拿到的Token数组是否真的有内容:
public function sendNotification(Request $request) { $firebaseToken = User::whereNotNull('device_token')->pluck('device_token')->all(); dd($firebaseToken); // 先打印这个数组,看看是不是空的 // ... 剩下的代码 }
如果打印出来是空数组,要么是数据库里没有用户的device_token值,要么是查询条件写错了(比如应该用where('device_token', '!=', '')而不是whereNotNull,如果字段默认是空字符串而不是null)。
3. 排查前端获取FCM Token的流程
前端如果拿不到Token,后端自然没的存:
- 打开浏览器控制台,看
console.log(token)有没有输出有效Token。如果没有,可能的原因:- 你的
firebaseConfig配置是否正确?检查apiKey、messagingSenderId、projectId这些参数是否和Firebase控制台一致。 - 网站是否是HTTPS环境?FCM在非HTTPS环境(除了localhost开发环境)下无法获取Token。
- 用户是否拒绝了通知权限?如果用户点了拒绝,
requestPermission()会进入catch分支,这时候要提示用户开启权限,比如在catch里加个alert:}).catch(function (err) { console.error('Notification permission denied:', err); alert('请开启浏览器通知权限,才能接收推送消息哦~'); });
- 你的
4. 优化后端发送逻辑,避免空数组请求
就算暂时没有用户的Token,也不要给FCM发送空的registration_ids,可以加个判断:
public function sendNotification(Request $request) { $firebaseToken = User::whereNotNull('device_token')->pluck('device_token')->all(); if(empty($firebaseToken)){ return response()->json(['message' => '没有可用的设备Token'], 400); } $SERVER_API_KEY = '你的FCM服务器密钥'; $data = [ "registration_ids" => $firebaseToken, "notification" => [ "title" => $request->title, "body" => $request->body, "sound" => "default" // 可选,添加通知声音 ] ]; $dataString = json_encode($data); $headers = [ 'Authorization: key=' . $SERVER_API_KEY, 'Content-Type: application/json', ]; $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, $headers); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // 建议开启SSL验证,更安全 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $dataString); $response = curl_exec($ch); $curlError = curl_error($ch); curl_close($ch); if($curlError){ return response()->json(['error' => $curlError], 500); } return response()->json(['fcm_response' => json_decode($response)]); }
按照上面的步骤一步步排查,应该就能找到问题所在啦~
内容的提问来源于stack exchange,提问作者kiana.ka
相关产品推荐
相关产品推荐

