2
1

More than 1 year has passed since last update.

【PHP】マッチ機能

Last updated at Posted at 2021-12-23

マッチングアプリによくあるマッチ機能を実装しました。
match 1.gif

スワイプカード

まずはスワイプを行うカードを作成します。
swipe_card.gif

<div class="card">
    <div class="matching_btn">
        <label>
            <div class="fa-image_range">
                <i class="fas fa-times-circle"></i>
            </div>
            <input type="button" id="unmatch_btn" style="display:none;">
        </label>
        <label>
            <div class="fa-image_range">
                <i class="fas fa-heart"></i>
            </div>
            <input type="button" id="match_btn" style="display:none">
        </label>
    </div>
</div>

<script src=" https://code.jquery.com/jquery-3.4.1.min.js "></script>
<script>
$(document).on('click', '#match_btn', function() {
    $('.card').animate({
        "marginLeft": "758px"
    }).fadeOut();
});

$(document).on('click', '#unmatch_btn', function() {
    $('.card').animate({
        "marginRight": "758px"
    }).fadeOut();
});
</script>

HTMLでカードのレイアウト、JavaScriptでボタンクリック時にカードが動くよう実装しています。

<i class="fas fa-times-circle"></i>
:
<i class="fas fa-heart"></i>

Font Awasome×を引用。

ユーザー数に合わせてカード作成

登録されているユーザー数だけ、カードを表示します。

$user = new User($current_user);
$users = $user->get_users("all");
foreach ($users as $user) :
    if ($user['id'] != $current_user['id']) :
        if (!check_match($user['id'], $current_user['id'])) :
?>
<div class="card">
    <label>
        <i class="far fa-times-circle profile_clear"></i>
        <input type="button" id="profile_clear">
    </label>
    <img src="/user/image/<?= $user['image'] ?>" class="mypage">
    <h3 class="profile_name"><?= $user['name'] ?></h3>
    <p class="comment"><?= $user['profile'] ?></p>
    <div class="matching_btn">
        <label>
            <div class="fa-image_range">
                <i class="fas fa-times-circle"></i>
            </div>
            <input type="button" id="unmatch_btn" style="display:none;">
        </label>
        <label>
            <div class="fa-image_range">
                <i class="fas fa-heart"></i>
            </div>
            <input type="button" id="match_btn" style="display:none">
        </label>
    </div>
</div>
<?php
        endif;
    endif;
endforeach;

$user->get_users("all")で現在登録されているユーザー情報を取得しており、
foreach関数でユーザー数だけカードを表示させています。
swipe_card1.gif
現状、すべてのカードが連動して処理に反応してしまうので、1枚1枚動かせるようにします。
また、レイアウトもカードが重なるように修正していきます。

<div class="card" id="match<?= $user['id'] ?>">
:
:
<i class="fas fa-times-circle"></i>
</div>
<input type="button" id="unmatch_btn" data-target="#match<?= $user['id'] ?>" style="display:none;">
<input type="hidden" class="unmatch_user_id" value="<?= $current_user['id'] ?>">
:
:
<input type="button" id="match_btn" data-target="#match<?= $user['id'] ?>" style="display:none">
<input type="hidden" id="modal<?= $user['id'] ?>_userid" value="<?= $user['id'] ?>">
<input type="hidden" class="match_user_id" value="<?= $current_user['id'] ?>">
</label>
<script>
$(document).on('click', '#unmatch_btn', function() {
    var target_modal = $(this).data("target");
    $(target_modal).animate({
        "marginRight": "758px"
    }).fadeOut();
});

$(document).on('click', '#match_btn', function() {  
    var target_modal = $(this).data("target");
    $(target_modal).animate({
        "marginLeft": "758px"
    }).fadeOut();
});
</script>

data-tagetを使用して、1枚1枚動くようにし、
style='position: absolute;'でカードが重ならないようにします。
swipe_card2.gif

ユーザIDを保存するマッチテーブル

カードをスワイプしたときに、ユーザIDを保存するテーブルを作成します。
image.png
matchテーブルスワイプされる側のユーザIDuser_idスワイプする側のユーザIDmatch_user_idとして保存します。
画面上だと、このようにDBに値が渡ります。
swipe_card4.gif
※ユーザIDはそれぞれ次のようになっています。
test_user:7
test_user2:8

では、ajax処理でカードスワイプ時にDBへ値が渡るようにします。
処理の流れはこちらと似ているので参考までに。

マッチボタンクリック時に、イベントが発火するようにします。

$(document).on('click', '#match_btn', function(e) {
    e.stopPropagation();
    var current_user_id = $('.match_user_id').val(),
        target_modal = $(this).data("target"),
        user_id = $('' + target_modal + '_userid').val();
    $.ajax({
        type: 'POST',
        url: '../ajax_match_process.php',
        dataType: 'text',
        data: {
            current_user_id: current_user_id,
            user_id: user_id
        }
    }).done(function() {
    }).fail(function() {
   });
});

マッチボタンをクリックすると処理が走り、ajax_match_process.phpに相互のユーザーIDを渡してmatchテーブルに更新されます。

// ajax_match_process.php

if (isset($_POST)) {
  $current_user_id = $_POST['current_user_id'];
  $user_id = $_POST['user_id'];
  $action = '登録';
  $flash_type = 'sucsess';
  $sql = "INSERT INTO `match`(user_id,match_user_id)
  VALUES(:user_id,:matched_user_id)";
  try {
    $dbh = db_connect();
    $stmt = $dbh->prepare($sql);
    $stmt->execute(array(':user_id' => $current_user_id, ':matched_user_id' => $user_id));
  } catch (\Exception $e) {
    error_log($e, 3, "../php/error.log");
    _debug('マッチ失敗');
    echo json_encode("error");
  }
}

このように取得したユーザーIDからDBへの更新を行っています。
次にuser_idmatch_user_idでお互いの値をもっているときに、モーダル画面を出力するイベントを発火させます。

※お互いの値をもっているときとは、下記のような状況のときです。
image.png

COOKIEを使ってマッチング画面表示

カードをスワイプして、お互いのユーザーIDを取得したときにCOOKIEを使ってマッチング画面を表示させます。
まずはajax_match_process.phpでDB更新時に、お互いのユーザーIDがあるか確認し、有ればCOOKIEを取得するような処理にします。

// ajax_match_process.php
:
:
    $stmt = $dbh->prepare($sql);
    $stmt->execute(array(':user_id' => $current_user_id, ':matched_user_id' => $user_id));
    if (count(check_matchs($user_id, $current_user_id)) == 2) {
      setcookie('username', 1, time() + 60 * 60 * 24 * 7);
    } else {
      setcookie('username', "", time() - 60);
    }
  } catch (\Exception $e) {
:
:
function check_matchs($user_id, $current_user_id)
{
    $dbh = db_connect();
    $sql = "SELECT user_id,match_user_id
        FROM `match`
        WHERE (user_id = :user_id and match_user_id = :match_user_id) or (user_id = :match_user_id and match_user_id = :user_id)";
    $stmt = $dbh->prepare($sql);
    $stmt->execute(array(
      ':user_id' => $current_user_id,
      ':match_user_id' => $user_id
    ));
}

check_matchs関数でお互いのユーザーIDがあるか確認をとり、有れば名前をusername、値を1としてCOOKIEを作成します。

<div class="modal_match" style="display:none"></div>
<div class="match_process" id="match<?= $user['id'] ?>" style="display:none">
    <h2 class="post_title"><?= $user['name'] ?>さんとマッチしました</h2>
    <img name="profile_image" class="matching_img" src="/user/image/<?= $user['image'] ?>">
</div>
<i class="far fa-times-circle match_clear" style="display:none"></i>

COOKIEの値が条件と合えば、こちらのモーダル画面を出力するようにします。
image.png

:
:
            current_user_id: current_user_id,
            user_id: user_id
        }
    }).done(function() {
        var cookies = document.cookie;
        var cookiesArray = cookies.split(';');

        for (var c of cookiesArray) {
            var cArray = c.split('=');
            if (cArray[0] == ' username') {
                $('.modal_match').fadeIn();
                $(match_modal).fadeIn();
                $('.match_clear').fadeIn();
                $(document).on('click', '.far.fa-times-circle.match_clear', function() {
                    $('.modal_match').hide();
                    $(match_modal).hide();
                    $('.far.fa-times-circle.match_clear').hide();
                });
            }
        }

COOKIEからusernameの値を取得し、有ればモーダル画面表示するようにします。
COOKIEからの値取得方法は下記Qiitaを参考にさせていただきました。

正常に動けば、このようにマッチ機能が動きます。
match 1.gif

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1