2018-10-31に更新

PHP+Laravel+FCMでWebプッシュ通知を送る

LaravelでFCMを使ったWebプッシュ通知を実装しましたが、検索してもあまりサンプルなどなかったので書き残しておきます。

Firebaseに登録

FCMはFirebase Cloud Messagingなので、とりあえずFirebaseに登録する必要があります。基本的には下記のとおりに行うだけです。

JavaScript Firebase Cloud Messaging クライアント アプリを設定する

このページの最初の方にJavaScriptに設定する方法が書かれたリンクもあります。

Firebase を JavaScript プロジェクトに追加する

このconfigの内容は、Firebaseの画面のProject Overviewというリンクをクリックした先の「ウェブアプリに Firebase を追加」というボタンをクリックすると出てきます。

Service Workerの設定

前述のマニュアルを読んで地味に気づいにくいのがService Workerの設定です。これを行わないと動きません。具体的には下記のページに書かれています。

JavaScript クライアントでメッセージを受信する

なんかプッシュ通知を送信したいのに「受信する」というタイトルなので初めて見た時は関係ないと思って飛ばしてしまって気づきませんでした。

Webプッシュ通知の許可

設定が終わったらあとはどんどん実装を進めていきます。最初は通知の許可です。これは結構みんな経験したことがあると思いますが、ブラウザで急に出てくる「通知を許可しますか?」みたいなやつです。

許可されたらトークンが取れるので、それをLaravel側に送信してユーザー情報に保存します。

import * as firebase from "firebase";
import axios from "axios";

const messaging = firebase.messaging();

messaging
  .requestPermission()
  .then(() => messaging.getToken())
  .then(token => {
    if (token) {
      const params = {
        token,
        user_agent: window.navigator.userAgent
      };
      return axios.post("/fcm-tokens", params);
    }
  })
  .then(response => {
    if (response && response.data.result) {
      console.log('Done');
    }
  })
  .catch(err => {
    console.log(err);
  });

上記のような感じで、ユーザーエージェントなどと紐付けてtokenを保存し、ユーザーのhasManyとして紐付けておきます。というのも、ユーザー毎ではなく操作する端末毎での許可になるので、1ユーザーにつき複数のtokenが紐づく形になるためです。

Laravel側

Laravel側ですが、今回僕は下記のライブラリを使用しました。

brozot/Laravel-FCM: Laravel-FCM

READMEを見てもらえば分かりますが、むちゃくちゃ簡単に必要な処理が可能です。

Webプッシュ通知する端末の登録

上記を使って、Laravel側では下記のようにして保存しました。

    public function store(Request $request)
    {
        $user = Auth::user();
        $fcmToken = FcmToken::firstOrNew([
            'user_id' => $user->id,
            'user_agent' => $request->input('user_agent'),
        ]);

        // 念の為
        if (!$fcmToken->id) {
            $fcmToken->token = $request->input('token');
            $fcmToken->save();
        }

        // 適当にユーザーのグループ名を作る
        $groupName = $user->getFcmGroupName();

        if ($user->notification_key) {
            FCMGroup::addToGroup($groupName, $user->notification_key, [$fcmToken->token]);
        } else {
            $user->notification_key = FCMGroup::createGroup($groupName, [$fcmToken->token]);
            $user->save();
        }

        return response()->json(['result' => true]);
    }

非常に簡単ではありますが、FCMを初めて実装する人は何がなんやら分からないと思いますので説明していきます。

本家のマニュアルにあるように、FCMでは複数の端末に一度にWebプッシュ通知を送る場合には、下記の方法があります。

・トピック メッセージングでは、特定のトピックにオプトインした複数の端末にメッセージを送信できます。
・端末グループ メッセージングでは、定義したグループに属する複数の端末にメッセージを送信できます。

つまり例えばある投稿をウォッチしている全ての端末にWebプッシュ通知を送りたい場合はトピックメッセージ、あるユーザーの端末全てに送りたい場合は端末グループメッセージを送る、ということです。

今回のサンプルはユーザーへの通知を想定しているため、端末グループメッセージの説明を行います。

        // 適当にユーザーのグループ名を作る
        $groupName = $user->getFcmGroupName();

グループ名の文字列が必要なため、メソッド化し一意になるような文字列を返しています。

        } else {
            $user->notification_key = FCMGroup::createGroup($groupName, [$fcmToken->token]);
            $user->save();

グループがまだ存在しない場合はまずグループを作成します。作成時には追加するトークンも一緒に指定することができます。取得した通知キーはWebプッシュ通知の際に使用するのでLaravel側でDBに保存しておきます。

        if ($user->notification_key) {
            FCMGroup::addToGroup($groupName, $user->notification_key, [$fcmToken->token]);

グループが既に存在する場合(PCで許可済みでスマホでも許可した場合等)には既に登録したグループに端末を追加するだけです。

Webプッシュ通知する端末の削除

FCMでWebプッシュ通知する端末を削除するのはLaravel側では下記のような処理になります。

        $groupName = $user->getFcmGroupName();
        FCMGroup::removeFromGroup($groupName, $user->notification_key, [$fcmToken->token]);

        $fcmToken->delete();

        if (!$user->fcmTokens()->count()) {
            $user->notification_key = null;
            $user->save();
        }

注意点として、マニュアルにも書かれていますがグループ内の端末が全てなくなった場合は、自動的にグループも削除されます。そのためユーザーに紐づくトークンを全て削除した場合はグループの通知keyも削除しておきましょう。

Webプッシュ通知を送信する

送信は非常に簡単です。Laravel-FCMにかかれている通りそのままです。アイコン指定は追記していますが、httpsから始まるフルURLを指定します。

        $notificationBuilder = new PayloadNotificationBuilder('新着コメント');
        $notificationBuilder->setBody("「{$post->name}」にコメントが投稿されました。")
            ->setIcon(config('app.url') . '/img/icon.png')
            ->setSound('default');

        $notification = $notificationBuilder->build();

        $groupResponse = FCM::sendToGroup($user->notification_key, null, $notification, null);

一点注意点として、Laravel-FCMのREADMEを見ると宛先を配列で指定していますが、今回はうまく動きませんでした。

これはたまたまなのかFCMの仕様なのか忘れてしまった&今回細かくは確認していないので、もし仕様であれば、一度にWebプッシュ通知を送信する宛先が多い場合は別途バックグラウンドで送信する、等が必要だと思われます。

もしくはトピックグループ送信でも良いと思いますが、管理が非常に大変になりそうだったので今回は使いませんでした。

まとめ

とりあえずざっとにはなりますがLaravelでFCMのWebプッシュ通知を送信する方法をまとめました。とりあえずここに書いた内容を理解できれば、あとは本家のマニュアルの方を見てもスムーズに理解できるのではないかと思います。細かい部分は本家のマニュアルも実際に確認してみてください。

ツイッターでシェア
みんなに共有、忘れないようにメモ

だら@Crieit開発者

Crieitの開発者です。 Webエンジニアです(在宅)。大体10年ちょい。 記事でわかりにくいところがあればDMで質問していただくか、案件発注してください。 業務依頼、同業種の方からのコンタクトなどお気軽にご連絡ください。 業務経験有:PHP, MySQL, Laravel, React, Flutter, Vue.js, Node, RoR 趣味:Elixir, Phoenix, Nuxt, Express, GCP, AWS等色々 PHPフレームワークちいたんの作者

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント