You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:54:08