質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.36%

ウェブサイトのプッシュ通知実装について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,664

ariiiiiga

score 46

簡易的な予約サイトを作っています。
店舗が予約の可否を表示し、利用客はサイト内で予約が完了するような流れです。

利用客が予約をした後に、予約を店舗へ知らせるためにプッシュ通知を送る必要があるのですが、その際の通知を送る条件を正しく予約が完了したら(予約完了画面へいけたら)通知を送る仕様にしたいです。

現状、ユーザー側の予約ページ(user_submit.php)で予約が完了したらuser_submit.phpでプッシュ通知が届くようになっています。
この通知を店舗側のページ(shop.php)にプッシュ通知を送りたいのですが、調べるための検索キーワードがわからないので教えて頂きたいです。

*DB名
users:ユーザー情報
shop:店舗情報
reserve:予約情報
subscription:shop.webpush.phpの'endpoint'、'p256dh'、'auth'

よろしくお願いします。

<user_submit.php>
// データの追加
<?php
require  'autoload.php';
require_once 'shop_webpush.php';


error_reporting(E_ALL);
ini_set("display_errors",1);

try {
  require("db_user_connect.php");
  require("db_usershop_connect.php");

  // セッションの開始
  $count = $_SESSION['count'];
  $time = $_SESSION['time'];
  $comment = $_SESSION['comment'];
  // 接続設定

  // データの追加
  $sql = "INSERT INTO reserve(reserve_shop_id,count,time,reserve_comment,reserve_tel) VALUES('".$shop_id."','".$count."','".$time."','".$comment."','".$tel."')";
  $stmt = $pdo -> prepare($sql);
  $stmt -> execute();
  if($stmt) {
      sendWebPush(); //Webpush call when reserve success.
  }

} catch (PDOException $e) {
  var_dump($e);
  die();
}
<autoload.php>

// autoload.php @generated by Composer

require_once __DIR__ . '/autoload_real.php';

return ComposerAutoloaderInit5211635af155434412c2432ac36ae6df::getLoader();
<?php
<autoload_real.php>
// autoload_real.php @generated by Composer

class ComposerAutoloaderInit5211635af155434412c2432ac36ae6df
{
    private static $loader;

    public static function loadClassLoader($class)
    {
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }

    public static function getLoader()
    {
        if (null !== self::$loader) {
            return self::$loader;
        }

        spl_autoload_register(array('ComposerAutoloaderInit5211635af155434412c2432ac36ae6df', 'loadClassLoader'), true, true);
        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
        spl_autoload_unregister(array('ComposerAutoloaderInit5211635af155434412c2432ac36ae6df', 'loadClassLoader'));

        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
        if ($useStaticLoader) {
            require_once __DIR__ . '/autoload_static.php';

            call_user_func(\Composer\Autoload\ComposerStaticInit5211635af155434412c2432ac36ae6df::getInitializer($loader));
        } else {
            $map = require __DIR__ . '/autoload_namespaces.php';
            foreach ($map as $namespace => $path) {
                $loader->set($namespace, $path);
            }

            $map = require __DIR__ . '/autoload_psr4.php';
            foreach ($map as $namespace => $path) {
                $loader->setPsr4($namespace, $path);
            }

            $classMap = require __DIR__ . '/autoload_classmap.php';
            if ($classMap) {
                $loader->addClassMap($classMap);
            }
        }

        $loader->register(true);

        if ($useStaticLoader) {
            $includeFiles = Composer\Autoload\ComposerStaticInit5211635af155434412c2432ac36ae6df::$files;
        } else {
            $includeFiles = require __DIR__ . '/autoload_files.php';
        }
        foreach ($includeFiles as $fileIdentifier => $file) {
            composerRequire5211635af155434412c2432ac36ae6df($fileIdentifier, $file);
        }

        return $loader;
    }
}

function composerRequire5211635af155434412c2432ac36ae6df($fileIdentifier, $file)
{
    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
        require $file;

        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
    }
}
<shop_webpush.php>
<?php
use Minishlink\WebPush\WebPush;
use Minishlink\WebPush\Subscription;

function sendWebPush() {
    try {

        $pdo = new PDO('mysql:host=localhost;dbname=reserve;charset=utf8','root','');
        $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        $query = "SELECT * FROM subscription";
        $stmt = $pdo->prepare($query);
        $stmt->execute();

        if (!$stmt) {
          print('ユーザークエリーが失敗しました。' . $pdo->error);
          $pdo->close();
          exit();
        }

        $subscriptions = array();
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
          $subscription = new stdClass;
          $subscription->endpoint = $row['endpoint'];
          $subscription->p256dh = $row['p256dh'];
          $subscription->auth = $row['auth'];
          array_push($subscriptions, $subscription);
        }


        $auth = array(
            'VAPID' => array(
                'subject' => 'localhost',
                'publicKey' => 'BMGh50KuOyQcXHWGQrzM_HjuCmC9Z03lqkBae9WFppVolNgUd16na_-2QjMXnCPfHx-j6cFRGXMAigIfzGeiy3U',
                'privateKey' => '1xnCy4tn7smJS8bvT9B9DOvNwD8yNT5E2_1DhoP5zVM',
            ),
        );

        $payload = [
            'title' => '通知があります。',
            'body' => 'HelloWorld',
            'link' => 'http://localhost/reserve/reserve_shop/shop_home.php'
        ];

        $webPush = new WebPush($auth);

        foreach ($subscriptions as $subscription) {
            $subscriptionCreated = Subscription::create([
                'endpoint' => $subscription->endpoint,
                'keys' => [
                      'p256dh' => $subscription->p256dh,
                      'auth' => $subscription->auth
                ],
            ]);
            $webPush->sendNotification(
                $subscriptionCreated,
                json_encode($payload)
            );
        }

        // $webPush->flush();

        foreach ($webPush->flush() as $report) {
            //flush
            $endpoint = $report->getRequest()->getUri()->__toString();

            }
        } catch (Exception $e) {
           var_dump($e);
        }

}
?>
<db_user_connect.php>
<?php
  session_start();
  $pdo = new PDO('mysql:host=localhost;dbname=reserve;charset=utf8','root','',);
  $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  if(!isset($_SESSION['user'])) {
    header("Location: user_index.php");
  }

  // ①ユーザーIDからユーザー名を取り出す
  $query = "SELECT * FROM users WHERE user_id=:user_id";
  $result = $pdo->prepare($query);
  $result->bindValue(':user_id', $_SESSION['user'], PDO::PARAM_INT);
  $result->execute();

  // ユーザー情報の取り出し
  while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
    $user_name = $row['user_name'];
    $user_id = $row['user_id'];
    $tel = $row['tel'];
  }
<db_usershop_connect.php>
<?php
  // 渡されたidを受け取る
  $shop_id = filter_input(INPUT_GET, 'shop_id', FILTER_SANITIZE_SPECIAL_CHARS);
  // 受け取ったidからレコード取得sqlを生成
  $sql = "SELECT * FROM shop WHERE shop_id = ".$shop_id;
  //SQL文を実行する
  $PostData = $pdo->query($sql);
  //実行結果を配列で受け取る
  $shop_result = $PostData->fetch( PDO::FETCH_ASSOC);

  if (!$shop_result) {
    print('shopクエリーが失敗しました。' . $pdo->error);
    $pdo->close();
    exit();
  }
  // ユーザー情報の取り出し
  $shop_name = $shop_result['shop_name'];
<save-subscription.php>
<?php

// データベースにSubscriptionを保存する。
$data = json_decode(file_get_contents("php://input"));
// make sure data is not empty
if(
    !empty($data->endpoint) &&
    !empty($data->keys)
){

    // set product property values
    $endpoint = $data->endpoint;
    $auth = $data->keys->auth;
    $p256dh = $data->keys->p256dh;

    // 保存する
    $query = "INSERT INTO
                subscription
            SET
                endpoint=:endpoint, auth=:auth, p256dh=:p256dh";
     //connect to DB
     $pdo = new PDO('mysql:host=localhost;dbname=reserve;charset=utf8','root','');
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);


    // Save Subscription to DB to push
    $subscription_stmt = $pdo->prepare($query);
    $subscription_stmt->bindValue(':endpoint',$endpoint , PDO::PARAM_STR);
    $subscription_stmt->bindValue(':auth', $auth, PDO::PARAM_STR);
    $subscription_stmt->bindValue(':p256dh', $p256dh, PDO::PARAM_STR);

    if($subscription_stmt->execute()) {
         // set response code - 201 created
        http_response_code(201);

        // tell the user
        echo json_encode(array("message" => "Subscription was created."));
    } else {
          // set response code - 503 service unavailable
        http_response_code(503);

        // tell the user
        echo json_encode(array("message" => "Unable to create Subscription."));
    }
} else {

    // set response code - 400 bad request
    http_response_code(400);

    // tell the user
    echo json_encode(array("message" => "Unable to create Subscription. Data is incomplete."));
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ariiiiiga

    2019/05/17 19:09

    ファイルを追加しましたが他に必要なことがあれば教えてください。

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2019/05/18 00:27 編集

    プッシュ通知である必要性がない気がします。
    普通にDBから読み取れば済むことではありませんか?
    それともプッシュ通知というものを取り違えていません?

    キャンセル

  • yasutomi

    2019/05/18 07:15

    Web Notification APIを使う必要があるような。
    https://developer.mozilla.org/ja/docs/WebAPI/Using_Web_Notifications

    キャンセル

回答 1

checkベストアンサー

0

<shop_webpush.php>

が使おうとしているのはPush APIですね。
ブラウザで管理画面を開いていなくても、通知を表示させるための仕組みです。

shop.php(管理画面上)にpushを送る仕組みではなく、SerivceWorkerというバックグラウンドプロセス的なものを予め登録して、そこからshowNotificationする仕組みになります。

ServiceWorkerの登録、通知許可の取得、subscriptionの保存(=>save_notification.php)の流れが必要なはずですが、そのコードがみあたらないですね。

Web Notification APIというのもあり、今回の場合はそちらで足りそうな気はします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.36%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る