戻る
■考察: テーブル設計
CREATE TABLE IF NOT EXISTS users( id INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '代理キー', created DATETIME NOT NULL COMMENT '作成日時', modified DATETIME NOT NULL COMMENT '更新日時', deleted DATETIME COMMENT '削除日時', username VARCHAR(80) NOT NULL UNIQUE COMMENT 'ユーザ名', password VARCHAR(80) COMMENT 'パスワード', password_salt VARCHAR(80) COMMENT 'パスワードのソルト', email VARCHAR(255) NOT NULL UNIQUE COMMENT 'メールアドレス', loggedin DATETIME COMMENT '最終ログイン日時', failed INT UNSIGNED COMMENT 'ログイン失敗回数', failed_last DATETIME COMMENT '最終ログイン失敗日時', option1 VARCHAR(80) NOT NULL COMMENT 'ユーザごとの設定例1', option2 VARCHAR(80) NOT NULL COMMENT 'ユーザごとの設定例2', option3 VARCHAR(80) NOT NULL COMMENT 'ユーザごとの設定例3', PRIMARY KEY(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT 'ユーザ'; CREATE TABLE IF NOT EXISTS devices( id INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '代理キー', created DATETIME NOT NULL COMMENT '作成日時', modified DATETIME NOT NULL COMMENT '更新日時', deleted DATETIME COMMENT '削除日時', code INT UNSIGNED NOT NULL UNIQUE COMMENT 'コード(識別コード。代理キーを非可逆暗号化すれば、推測も重複も避けられそう)', useragent VARCHAR(255) NOT NULL COMMENT 'ユーザエージェント(あまり意味がないかもしれないが、一応記録しておくか)', platform VARCHAR(20) NOT NULL COMMENT 'プラットフォーム(例: ios / android)', os_version VARCHAR(80) NOT NULL COMMENT 'OSバージョン(例: 13.2.3)', app_version VARCHAR(80) NOT NULL COMMENT 'アプリバージョン(例: 1.0.2)', ip VARCHAR(80) NOT NULL COMMENT '最終IPアドレス', token VARCHAR(255) UNIQUE COMMENT 'デバイストークン', endpoint VARCHAR(255) COMMENT 'エンドポイント', disabled DATETIME COMMENT '無効日時', notification TINYINT(1) UNSIGNED NOT NULL COMMENT '通知', # この設定は不要か。OSレベルで通知がOFFでもとりあえず送信&受け取りは行われる?アプリ内で設定のON/OFFを設ける場合には必要そう option1 VARCHAR(80) NOT NULL COMMENT 'デバイスごとの設定例1', option2 VARCHAR(80) NOT NULL COMMENT 'デバイスごとの設定例2', option3 VARCHAR(80) NOT NULL COMMENT 'デバイスごとの設定例3', user_id INT UNSIGNED NOT NULL COMMENT '外部キー ユーザ', loggedin DATETIME COMMENT '最終ログイン日時', loggedout DATETIME COMMENT '最終ログアウト日時', PRIMARY KEY(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT 'デバイス';
■以下は要検討 アプリ起動時にインターネットに繋がっていなければどうするか アプリの起動自体ができない…などは避けたい サーバ上の設定を取得する必要があるなら、その内容はアプリ内に保持しておいて起動時に毎回更新するか アプリ内の設定でプッシュの有効/無効を切り替えたとき、実装内容によっては一斉配信用のトピックからも追加/除外する必要がある 何かしらの通信エラーでデータベース内の値とトピックの値が異なると問題なので、データベースのロールバックなどを活用する 「データベースから削除 → トピックから削除 → 正常終了ならコミット/そうでなければロールバック」 で対応できるか アプリデータを初期化して起動した場合など、同じデバイストークンがすでにデータベースに登録されている可能性はある プッシュが重複して何度も届かないように、初回起動の新規登録時は「すでに同じデバイストークンのデータがあれば、そのデバイストークンはNULLにする。user_idもNULLにする」としておく 仮に「すでに同じデバイストークンのデータがあれば、そのデータを自身のデータとして紐付ける」をすると、「アプリを初期化したのに何故かデータが復元される」となるので避ける ログインした状態でアプリの設定をリセットしたら、サーバサイドでは「ログイン中」の情報が残ってしまうが、 次回初回起動の新規登録時、古いデータのデバイストークンとuser_idにはNULLが登録されるので大丈夫のはず お知らせの未読数をアプリのアイコンに表示する場合、既読数もしくは未読数をサーバサイドで管理する必要がある (プッシュを送信する際に、「アイコンの数字には何を表示するか」を指定する必要があるため) が、それだとトピックへの一斉配信が使えない(同一の内容を送信するため、ユーザごとの既読数などは送れない) プッシュを受け取ってからアプリ側で数字をインクリメントさせる必要があるが、通常のプッシュだとバックグラウンド時に受信したときの処理を指定できない サイレントプッシュを使えば一応は可能だが、バッジのためだけに常にサイレントプッシュを使うのもイマイチか 「何かしらのお知らせがあれば1と表示する」のように簡易な実装にする方が無難そう iOSのサイレントプッシュを試してみる - しめ鯖日記 http://www.cl9.info/entry/2017/10/14/145342 Swiftでサイレントプッシュを送る - ニフクラ mobile backend(mBaaS)お役立ちブログ https://blog.mbaas.nifcloud.com/entry/2018/11/06/144238 iOS 13以上でサイレントプッシュのdidReceiveRemoteNotificationが呼ばれない問題 - Qiita https://qiita.com/knagauchi/items/64dd9d57f123a24a4e14