【PHP】フォロー機能実装

PHPについて学習内容を備忘録としてまとめます。
ユーザー間のフォロー機能を実装しましたので、作成方法を記載します。

![anime1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/53d68c1b-ee1f-51f8-84be-fca8e56090aa.gif)
完成したものは上記のようにフォローボタンを押すと、
`フォローした人`と`フォロワー`の情報がテーブルに渡されます。

#テーブル構成
まずは`フォローした人`と`フォロワー`の情報を扱うため、そのテーブルを作成します。
テーブルの構成は下記のようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/b1c01b4e-43e9-82bd-dc81-51d79b5402bb.png)
`relation`がテーブル名、`follow_id`と`follower_id`がカラム名になっております。
名前はご自身でお好みでつけても問題ございません。

※動作画面に`id`カラムと`delete_flg`カラムがありますが、こちらはなくても実装できます。
#フォローボタン実装
フォローボタンを表示させます。
表示先のページは`フォローするユーザーのページ`を指定しています。

```php
$current_user = get_user($_GET['user_id']);
$profile_user = get_user($_GET['page_id']);

<form action="#" method="post">
          <input type="hidden" class="current_user_id" value="<?= $current_user['id'] ?>">
          <input type="hidden" name="follow_user_id" value="<?= $user_id ?>">
          <?php if (check_follow($current_user['id'],$user_id)): ?>
          <button class="follow_btn border_white btn following" type="button" name="follow">フォロー中</button>
          <?php else: ?>
          <button class="follow_btn border_white btn" type="button" name="follow">フォロー</button>
          <?php endif; ?>
</form>
```
まず、`get_user()`を使用して`ログイン中のユーザー情報`と`ページ内のユーザー情報`を取得しています。
`get_user()`は下記のような構成の関数になっており、引数にあるユーザーIDからユーザー情報を返します。

```php
function get_user($user_id){
    try {
      $dsn='mysql:dbname=shop;host=localhost;charset=utf8';
      $user='root';
      $password='';
      $dbh=new PDO($dsn,$user,$password);
      $sql = "SELECT id,name,password,profile,image
              FROM user
              WHERE id = :id AND delete_flg = 0 ";
      $stmt = $dbh->prepare($sql);
      $stmt->execute(array(':id' => $user_id));
      return $stmt->fetch();
    } catch (\Exception $e) {
      error_log('エラー発生:' . $e->getMessage());
      set_flash('error',ERR_MSG1);
    }
  }
```
戻りまして、

```php
$current_user = get_user($_GET['user_id']);
$profile_user = get_user($_GET['page_id']);
```
`$_GET['user_id']`と`$_GET['page_id']`に関してはパスからユーザーIDを取得しています。

```
http://localhost/user/user_disp.php?user_id=20&page_id=23
```
このようなパスになっていた場合は`$_GET['user_id']`に`20`、`$_GET['page_id']`に`23`が渡されます。

```js
function check_follow($follow_user,$follower_user){
  $dsn='mysql:dbname=shop;host=localhost;charset=utf8';
  $user='root';
  $password='';
  $dbh=new PDO($dsn,$user,$password);
  $sql = "SELECT follow_id,follower_id
          FROM relation
          WHERE :follower_id = follower_id AND :follow_id = follow_id";
  $stmt = $dbh->prepare($sql);
  $stmt->execute(array(':follow_id' => $follow_user,
                       ':follower_id' => $follower_user));
  return  $stmt->fetch();
}
```
次に`check_follow`関数でユーザーがフォロー関係にあるか確認をしています。
引数に渡されたユーザーIDが`relartionテーブル`でフォロー関係にあった場合は`true`を返し、フォロー関係にない場合は`false`を返します。

```
          <?php if (check_follow($current_user['id'],$user_id)): ?>
          <button class="follow_btn border_white btn following" type="button" name="follow">フォロー中</button>
          <?php else: ?>
          <button class="follow_btn border_white btn" type="button" name="follow">フォロー</button>
          <?php endif; ?>
```
フォローボタンを表示していたブラウザ画面に戻りまして、先ほどの`check_follow`関数で`true`が返ってきた場合は`フォロー中`、`false`が返ってきた場合は`フォロー`がボタンに表示されます。

これでフォローボタンの実装が完了したので、今度はクリックした際の`ajax処理`についてみていきます。

#ajax処理_js
フォローボタンをクリックした時にデータベースを操作するajax処理について実装していきます。
jsファイルに下記ソースコードを入力していきます。

```js
  $(document).on('click','.follow_btn',function(e){
    e.stopPropagation();
    var $this = $(this),
    current_user_id = $('.current_user_id').val();
    user_id = $this.prev().val();
    $.ajax({
        type: 'POST',
        url: '../ajax_follow_process.php',
        dataType: 'json',
        data: { current_user_id: current_user_id,
                user_id: user_id }
    }).done(function(data){
      location.reload();
    }).fail(function(){
      location.reload();
    });
  });
```
処理としては要素名が`.follow_btn`のフォローボタンがクリックされたときに、`current_user_id`と`user_id`を取得し`ajax_follow_process.php`に遷移しています。
細かく処理をみていきます。

```js
  $(document).on('click','.follow_btn',function(e){
    e.stopPropagation();
    var $this = $(this),
    current_user_id = $('.current_user_id').val();
    user_id = $this.prev().val();
```
`$(document).on('click','.follow_btn',function(e){`でフォローボタンがクリックされた際に処理が走るように定義されております。
そして`current_user_id = $('.current_user_id').val();`と`user_id = $this.prev().val();`でブラウザからユーザー情報を取得しています。

```php
<input type="hidden" class="current_user_id" value="<?= $current_user['id'] ?>">
<input type="hidden" name="follow_user_id" value="<?= $user_id ?>">
```
こちらは先ほどフォローボタンを表示していたブラウザ画面なのですが、`$('.current_user_id').val();`で`<?= $current_user['id'] ?>`、`user_id = $this.prev().val();`で`<?= $user_id ?>`をそれぞれ取得しています。

```js
    $.ajax({
        type: 'POST',
        url: '../ajax_follow_process.php',
        dataType: 'json',
        data: { current_user_id: current_user_id,
                user_id: user_id }
```
フォローボタンがクリックされたときにこちらの処理が走り取得したユーザー情報を`ajax_follow_process.php`に渡し遷移します。

```js
    }).done(function(data){
      location.reload();
    }).fail(function(){
      location.reload();
    });
```
こちらではajax処理が成功した場合と、失敗した場合で処理が分岐しています。
今回の場合だとどちらも`location.reload();`なのでページをリロードして終わりです。
それでは遷移した`ajax_follow_process.php`での処理をみていきます。

#ajax処理_PHP

```ajax_follow_process.php
  $user_id = $_POST['user_id'];
  $current_user_id = $_POST['current_user_id'];

    if(check_follow($current_user_id,$user_id)){
      $action = '解除';
      $flash_type = 'error';
      $sql ="DELETE
              FROM relation
              WHERE :follow_id = follow_id AND :follower_id = follower_id";
    }else{
      $action = '登録';
      $flash_type = 'sucsess';
      $sql ="INSERT INTO relation(follow_id,follower_id)
              VALUES(:follow_id,:follower_id)";
    }
    try {
      $dsn='mysql:dbname=shop;host=localhost;charset=utf8';
      $user='root';
      $password='';
      $dbh=new PDO($dsn,$user,$password);
      $stmt = $dbh->prepare($sql);
      $stmt->execute(array(':follow_id' => $current_user_id , ':follower_id' => $user_id));
      $return = array('action' => $action,
      'follow_count' => current(get_user_count('follow',$current_user_id)),
      'follower_count' => current(get_user_count('follower',$current_user_id)));
      echo json_encode($return);       
    }    
    catch (\Exception $e) {
      error_log('エラー発生:' . $e->getMessage());
      set_flash('error',ERR_MSG1);
      echo json_encode("error");
    }
```
jsファイルから取得したユーザー情報からフォロー関係にあるか確認し、返ってきた真偽値によって`relation`テーブルを操作して処理を行っています。

これでフォロー機能が実装できたと思います。
先ほどの動作画面のようにフォローボタンをクリックしたときに`relation`テーブルが操作される処理がされるはずです。

#参考URL
https://github.com/nyann123/snspoi