【PHP】メッセージ通知数表示

学習内容を備忘録としてまとめます。
メッセージ通知数表示機能を実装しましたので、作成方法を記載します。
![message_tsuuchisuu6.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/6890f446-9df8-8ac0-70e2-d3226bbe3e0b.gif)

※通知数の表示は赤枠で囲っています

メッセージ機能については、下の記事で説明しているので割愛します。
>[【PHP】メッセージ機能実装](https://qiita.com/ryouya3948/items/3d471b24b9ff62c3ad0d)

#実装方法
実装方法について記載していきます。

##テーブル構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/9f8f00a7-e757-9f7d-3361-24b965acc668.png)
`messatge_relationテーブル`に`message_count`を追加します。
このカラムは、ユーザー間にメッセージのやり取りがあった際にインクリメントされ、
通知数を表示するときは`message_count`カラムから、値を取り出して表示させます。

##全体の流れ
本機能を、関数とカラム値の遷移を踏まえて全体的な流れをみていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/fe6e0234-aa53-25a9-ed4e-a2b596f3ffe0.png)
##通知数をカウント
では、メッセージのやり取りがある際に`message_count`カラムの値をインクリメントするよう実装します。

```message_add.php
:
    $stmt->execute($data);
    $dbh = null;

    if (!check_relation_message($user_id, $destination_user_id)) {
        insert_message($user_id, $destination_user_id);
    }
    insert_message_count($user_id,$destination_user_id);　//ココ
    set_flash('sucsess', 'メッセージを送信しました');
    header('Location:../message/message.php?user_id=' . $destination_user_id . '');
:
```
メッセージを送信するときに、`insert_message_count`で値をインクリメントしています。

```php
insert_message_count($user_id,$destination_user_id);
```
引数には`自分のユーザーID`と`送信先のユーザーID`を渡しています。

```php
function insert_message_count($user_id,$destination_user_id){
  try {
    $dsn='mysql:dbname=db;host=localhost;charset=utf8';
    $user='root';
    $password='';
    $dbh=new PDO($dsn,$user,$password);
    $sql = "UPDATE message_relation
            SET message_count = message_count + 1
            WHERE ((user_id = :user_id and destination_user_id = :destination_user_id) or (user_id = :destination_user_id and destination_user_id = :user_id)) and user_id = :user_id";
    $stmt = $dbh->prepare($sql);
    $stmt->execute(array(':user_id' => $user_id,
                         ':destination_user_id' => $destination_user_id));
    return $stmt->fetch();
  } catch (\Exception $e) {
    error_log('エラー発生:' . $e->getMessage());
    set_flash('error',ERR_MSG1);
  }
}
```
`UPDATE`文で`message_count`をインクリメントしています。
条件文(where)ではメッセージのやり取りをしているユーザー同士のIDから該当の`message_relation`の列を取得して、`message_relation.user_id`がログイン中のユーザーIDと一致するようにしています。

`message_relation.user_id`をログイン中のユーザーidとする理由としては、表示する通知数を取得する際にこちらのカラムを利用するからです。
後ほど、詳しく説明します。

##通知数を表示
相手からメッセージが届いていた時に、通知数を表示する処理を実装します。

```message_top.php
:
foreach ($message_relations as $message_relation):
if($message_relation['destination_user_id']==$current_user['id']){
$destination_user=get_user($message_relation['user_id']);
}else{
$destination_user=get_user($message_relation['destination_user_id']);
}
$bottom_message=get_bottom_message($current_user['id'],$destination_user['id']);
$new_message_count=current(new_message_count($current_user['id'],$destination_user['id']));　//ココ
?>
:
    <div class="message_notification">
        <span id="message_count">
            <?php if($new_message_count!=0){  //
            print''.$new_message_count.'';  　//ココ
            }?>                               //
        </span>
    </div>
:
```
変数`$new_message_count`に通知数を渡します。

```php
function new_message_count($user_id,$destination_user_id){
  try {
    $dsn='mysql:dbname=db;host=localhost;charset=utf8';
    $user='root';
    $password='';
    $dbh=new PDO($dsn,$user,$password);
    $sql = "SELECT message_count
            FROM message_relation
            WHERE ((user_id = :user_id and destination_user_id = :destination_user_id) or (user_id = :destination_user_id and destination_user_id = :user_id)) and user_id = :destination_user_id";
    $stmt = $dbh->prepare($sql);
    $stmt->execute(array(':user_id' => $user_id,
                         ':destination_user_id' => $destination_user_id));
    return $stmt->fetch();
  } catch (\Exception $e) {
    error_log('エラー発生:' . $e->getMessage());
    set_flash('error',ERR_MSG1);
  }
}
```
引数のユーザーIDから通知数を取得しており、
条件文(where)では自分と相手のIDから`message_relation`の列を探して、`user_id`が相手のIDのものを取得しています。
そうすることで、先ほどインクリメントしていた`message_count`カラムの値が取得できます。

```message_top.php
:
    <div class="message_notification">
        <span id="message_count">
            <?php if($new_message_count!=0){  //
            print''.$new_message_count.'';  　//ココ
            }?>                               //
        </span>
    </div>
:
```
あとは表示したい場所に`$new_message_count`を表示させます。
0のときは表示をしないようにします。

##通知数をリセット
メッセージ画面を開いたときに通知数を0にします。
これをしないとメッセージトップ画面に戻っても、まだ通知数が表示されてしまうからです。

```message.php
:
$messages = get_messages($current_user['id'], $destination_user['id']);
$bottom_message=get_bottom_message($current_user['id'],$destination_user['id']);
reset_message_count($current_user['id'],$destination_user['id']);  //ココ
?>

<body>
:
```

`reset_message_count`関数では該当のカラムに0を渡します。

```php
function reset_message_count($user_id,$destination_user_id){
  try {
  $dsn='mysql:dbname=db;host=localhost;charset=utf8';
  $user='root';
  $password='';
  $dbh=new PDO($dsn,$user,$password);
  $dbh->beginTransaction();
  $sql = 'UPDATE message_relation SET message_count = 0 WHERE ((user_id = :user_id and destination_user_id = :destination_user_id) or (user_id = :destination_user_id and destination_user_id = :user_id)) and user_id = :destination_user_id';
  $stmt = $dbh->prepare($sql);
  $stmt->execute(array(':user_id' => $user_id,
                       ':destination_user_id' => $destination_user_id));
  $dbh->commit();
} catch (\Exception $e) {
  error_log('エラー発生:' . $e->getMessage());
  set_flash('error',ERR_MSG1);
  $dbh->rollback();
  reload();
}
}
```
先ほどの`new_message_count`関数と同様の条件文(where)で列を取得して、0を渡します。

上記が実装できれば、トップの動作画面のようになると思います。

#【おまけ】新規メッセージ件数の通知
![message_tsuuchisuu5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/f139e391-c609-d610-1357-384a11a6bc58.gif)
※通知数の表示は赤枠で囲っています

新しいメッセージがあると、ログイン時に件数を通知する機能を実装します。

フラッシュメッセージ機能については、下の記事で説明しているので割愛します。
>[【PHP】フラッシュメッセージの実装](https://qiita.com/ryouya3948/items/a2fcf2699ca630b29bf2)

##新規メッセージ数の取得
ログイン時に新しいメッセージあるか、DBを確認します。

```user_login_check.php
:
	$_SESSION['user_id']=$rec['id'];
	$_SESSION['user_name']=$rec['name'];
	if(current(message_count($_SESSION['user_id']))!=0){　//ココ
	set_flash('sucsess','ログインしました		メッセージが'.current(message_count($_SESSION['user_id'])).'件届いています');　//ココ
	}else{
	set_flash('sucsess','ログインしました');
	}
	header('Location:user_top.php?page_id='.$rec['id'].'&type=main');
:
```
新規メッセージがあれば、`message_count`関数を使用して件数をフラッシュメッセージで表示します。