グループごとにプッシュ通知を送信する
[プッシュ通知の許可を任意のタイミングで行えるようにする] の続きです。前回PHPとMySQLを使ってエンドポイントを保存することができたので複数のエンドポイントを呼び出して、呼び出されたものだけに対して通知を行えるようになったのでまとめ。
動きとしてはAさんのブログ記事が投稿をされたら、Aさんのブログを購読しているBさん、Cさんに対してプッシュ通知を送信する。
ブログの記事を管理する\_entryテーブル、購読者とブログ名を紐付ける\_subscribeテーブル、購読者と購読者のエンドポイントを管理する\_registerテーブルの3つを用意した。
基本的にService Worker側のコードは[最近流行りのWeb Push(プッシュ通知)を試してみる]をベースに一部を変更。
Service Workerはpushイベントを受け取って、エンドポイントごとに表示される内容を変えるためにnotifications.phpにクエリを投げるだけ。
```javascript
const getEndpoint = () => {
return self.registration.pushManager.getSubscription().then(subscription => {
if (subscription) {
return subscription.endpoint;
}
throw new Error('User not subscribed');
});
}
self.addEventListener('push', event => {
event.waitUntil(getEndpoint().then(endpoint => {
return fetch('./notifications.php?endpoint=' + endpoint);
}).then(response => {
if (response.status === 200) {
return response.json();
}
throw new Error('notification api response error')
}).then(json => {
return self.registration.showNotification(json.title, {
icon: json.icon,
body: json.body,
data: {
url: json.url
}
});
}));
});
self.addEventListener('notificationclick', event => {
event.notification.close();
clients.openWindow(event.notification.data.url);
}, false);
```
Aさんの記事投稿と共に呼び出されるpush.phpで購読者のエンドポイントに通知を投げる。
```php
try {
$pdo = new PDO('mysql:host=localhost;dbname=db_name;charset=utf8', 'root', 'password');
} catch (PDOException $e) {
exit('データベース接続失敗'.$e->getMessage());
}
$stmt = $pdo->query("
SELECT endpoint
FROM _register
JOIN _subscribe
ON _register.member_id = _subscribe.subscriber_id
JOIN _entry
ON _subscribe.subscription_blog_id = _entry.blog_id
WHERE entry_id = (
SELECT entry_id
FROM _entry
ORDER BY entry_id DESC
LIMIT 1)
");
while($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
$registration_ids[] = str_replace(FCM_API_URL, "", $result['endpoint']);
}
$pdo = null;
```
Bさん、CさんはService Workerでpushイベントを受け取るが、通知の内容が分からないので、notifications.phpに尋ねて結果をService Workerに返す。
```php
try {
$pdo = new PDO('mysql:host=localhost;dbname=db_name;charset=utf8', 'root', 'password');
} catch (PDOException $e) {
exit('データベース接続失敗'.$e->getMessage());
}
$stmt = $pdo->query("
SELECT *
FROM _register
JOIN _subscribe
ON _register.member_id = _subscribe.subscriber_id
JOIN _entry
ON _subscribe.subscription_blog_id = _entry.blog_id
WHERE entry_id = (
SELECT entry_id
FROM _entry
ORDER BY entry_id DESC
LIMIT 1)
");
$result = $stmt->fetch(PDO::FETCH_ASSOC);
echo('{
"title": "' . $result['blog_id'] . '",
"icon": "./favicon.ico",
"body": "' . $result['entry_title'] . '",
"url": "https://' . $result['blog_id'] . '.' . $_SERVER["HTTP_HOST"] . '"
}');
```
SQLについては改善の余地がありそう。
[プッシュ通知の許可を任意のタイミングで行えるようにする]: https://hi97.hamazo.tv/e8239503.html
[最近流行りのWeb Push(プッシュ通知)を試してみる]: https://qiita.com/kite_999/items/e53b1c60a10275988604
const content = document.getElementById('content');
content.innerHTML = marked(content.innerHTML.replace(/>/g, '>').replace(/</g, '
関連記事