【独学】はじめてのWebプログラミング – 9.9 Webページ開発 2-⑨

いいね機能の作成

いいねモデルの作成

Modelsフォルダ内に「likes.php」ファイルを作成します。

likes.phpに以下の内容を書きます。

htdocs/Twitter/Models/likes.php

<?php

// 設定ファイルの読み込み
include_once '../config.php';

function createLike($data)
{
    // データベースに接続
    $mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);

    // 成功/失敗確認
    if ($mysqli->connect_errno) {
        echo 'MySQLの接続に失敗しました。<br>';
        exit;
    }

    // いいね登録のSQLを作成
    $query = 'INSERT INTO likes (user_id, tweet_id) VALUES (?, ?)';
    
    // セキュリティ上、以下のように書く
    $statement = $mysqli->prepare($query);
    $statement->bind_param('ii', $data['user_id'], $data['tweet_id']);

    // SQLを実行
    $response = $statement->execute();

    // 成功/失敗確認
    if ($response == false) {
        echo 'エラーが発生しました。<br>';
        $response = null;
    } else{
        // 成功したら挿入したデータの主キー(likesテーブルのidカラムの値)を取得できる
        $response = $mysqli->insert_id;
    }

    // データベースへの接続解除
    $statement->close();
    $mysqli->close();

    // response変数には、id(成功)or null(失敗)が入っている
    return $response;
}

function deleteLike($data)
{
    // データベースに接続
    $mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);

    // 成功/失敗確認
    if ($mysqli->connect_errno) {
        echo 'MySQLの接続に失敗しました。<br>';
        exit;
    }

    // いいねを削除するSQLを作成
    $query = 'UPDATE likes SET status ="deleted" WHERE id = ? AND user_id = ?';

    // セキュリティ上、以下のように書く
    $statement = $mysqli->prepare($query);
    $statement->bind_param('ii', $data['like_id'], $data['user_id']);

    // SQLを実行
    $response = $statement->execute();

    // 成功/失敗確認
    if ($response == false) {
        echo 'エラーが発生しました。<br>';
    }

    // データベースへの接続解除
    $statement->close();
    $mysqli->close();

    // response変数には、true(成功)or false(失敗)が入っている
    return $response;
}

?>

いいねを登録するcreateLike関数を追加しています。
引数として、連想配列(登録するユーザー情報とツイート情報を含む)を受け取るものとします。
「$response = $mysqli->insert_id」に着目して下さい。insert_idはmysqliクラスがもつ変数です。主キーをもつテーブルにデータを挿入した場合、その主キーの値(ここでは、likesテーブルのidカラムの値)を取得することができ、その値がinsert_idに入っています。
その他はこれまでに解説した内容と同様です。

また、いいねを削除するdeleteLike関数を追加しています。
likesテーブルのstatusカラムの値を「deleted」に更新することで、削除状態になったことにしています。

上記では、「delete from テーブル」を使ってテーブルのレコードを削除するのではなく、特定のカラムの値をつかって削除状態にしています。

前者のテーブルのレコードを削除することを「物理削除」といい、
後者の特定のカラムの値をつかって削除状態にすることを「論理削除」といいます。

後々、集計処理のようなことをしたい場合に論理削除を使います。
レコードを削除してしまうと、完全にデータが消えてしまうためです。

いいねコントローラーの作成

Controllersフォルダ内に「like.php」ファイルを作成します。

VSCode

like.phpに以下の内容を書きます。

htdocs/Twitter/Controllers/like.php

<?php

include_once '../util.php';

// いいねモデルを読み込み
include_once '../Models/likes.php';

// ログインチェック
$view_user = getSession();
if ($view_user == false) {
    // ログインしていない
    header('Location: ../Controllers/sign-in.php');
    exit;
}

$like_id = null;

// いいねの登録
if (isset($_POST['tweet_id'])) {
    $data = [
        'tweet_id' => $_POST['tweet_id'],
        'user_id' => $view_user['id'],
    ];

    $like_id = createLike($data);
}

// いいねの取り消し
if (isset($_POST['like_id'])) {
    $data = [
        'like_id' => $_POST['like_id'],
        'user_id' => $view_user['id'],
    ];

    deleteLike($data);
}

// JSON形式で結果をクライアントに応答
$response = [
    'message' => 'success',
    'like_id' => $like_id,  // like_id変数には、id(成功)or null(失敗)が入っている
];
header('Content-Type: application/json; charset=uft-8');
echo json_encode($response);

?>

クライアントからのPOSTで、$_POST[‘tweet_id’]がセットされていれば、いいねを登録します。そうではなく、$_POST[‘like_id’]がセットされていれば、いいねの取り消しを行います。

最後に結果をクライアントに応答します。
JSON形式とは下図のようなデータの形式を指します。

JSONの説明

次の「header(‘Content-Type: application/json; charset=uft-8’)」のように書くことで、クライアントに「このデータはJSON形式のデータです」と教えることができます。これは覚えるしかありません。

最後に、変数$responseは連想配列ですので、json_encode関数を使って、連想配列からJSON形式に変換しています。json_encodeはPHPの関数です。
その戻り値(JSON形式のデータ)をechoすることで、JSON形式のデータがクライアントに通知(出力)されるのです。

ツイート領域の変更

ツイート領域を以下のように修正します。

htdocs/Twitter/Views/common/tweet.php

<div class="tweet">
    <div class="user">
        <a href="profile.php?user_id=<?php echo $view_tweet['user_id']; ?>">
            <img src="img_uploaded/user/<?php echo $view_tweet['user_image_name']; ?>" alt="">
        </a>
    </div>
    <div class="content">
        <div class="name">
            <a href="profile.php?user_id=<?php echo $view_tweet['user_id']; ?>">
                <span class="nickname"><?php echo $view_tweet['user_nickname']; ?></span>
                <span class="user-name">@<?php echo $view_tweet['user_name']; ?> ・<?php echo $view_tweet['tweet_created_at']; ?></span>
            </a>
        </div>
        <p><?php echo $view_tweet['tweet_body'] ?></p>

        <?php if (isset($view_tweet['tweet_image_name'])) : ?>
            <img src="<?php echo $view_tweet['tweet_image_name']; ?>" alt="" class="post-image">
        <?php endif; ?>

        <div class="icon-list">
            <!-- ★変更箇所(ここから) -->
            <div class="like js-like" data-tweet-id="<?php echo $view_tweet['tweet_id']; ?>" data-like-id="<?php echo $view_tweet['like_id']; ?>">
            <!-- ★変更箇所(ここまで) -->
                <?php
                    if (isset($view_tweet['like_id'])) {
                        // いいね!がある場合
                        echo '<img src="../Views/img/heart.svg" alt="">';
                    } else {
                        // いいね!がない場合
                        echo '<img src="../Views/img/heart2.svg" alt="">';
                    }
                ?>
            </div>
            <div class="like-count js-like-count"><?php echo $view_tweet['like_count']; ?></div>
        </div>
    </div>
</div>

「data-tweet-id=”<?php echo $view_tweet[‘tweet_id’]; ?>”」を追加しています。これはlikes.jsで使います。

いいね通知機能の作成

likes.jsを以下のように修正します。

htdocs/Twitter/Views/js/likes.js

$(function() {
    // いいね!がクリックされたとき
    $('.js-like').click(function() {
        const this_obj = $(this);
        // ★変更箇所1(ここから)
        const tweet_id = $(this).data('tweet-id');
        // ★変更箇所1(ここまで)
        const like_id = $(this).data('like-id');
        const like_count_obj = $(this).parent().find('.js-like-count');
        let like_count = Number(like_count_obj.html());

        if (like_id) {
            // ★変更箇所2(ここから)
            $.ajax({
                url: 'like.php',
                type: 'POST',
                data: {
                    'like_id': like_id
                }
            })
            .done(function() {
                // いいね!取り消し(カウントを減らす)
                like_count -= 1;
                like_count_obj.html(like_count);
                this_obj.data('like-id', null);

                // いいね!ボタンの色を変更
                this_obj.find('img').attr('src', '../Views/img/heart2.svg');
            });
            // ★変更箇所2(ここまで)
        } else {
            // ★変更箇所3(ここから)
            $.ajax({
                url: 'like.php',
                type: 'POST',
                data: {
                    'tweet_id': tweet_id
                }
            })
            .done(function(data) {
                // いいね!付与(カウントを増やす)
                like_count += 1;
                like_count_obj.html(like_count);
                this_obj.data('like-id', data['like_id']);

                // いいね!ボタンの色を変更
                this_obj.find('img').attr('src', '../Views/img/heart.svg');
            });
            // ★変更箇所3(ここまで)
        }
    });
})

変更箇所1では、tweet.phpで追加した「data-tweet-id」属性の値を取り出しています。

変更箇所2について解説します。
「$.ajax()」はjQueryの関数で、サーバーに対してHTTPリクエストを送ることができます。引数としてJSON形式のデータを渡します。これは覚えるしかありません。
引数のJSON形式のデータについてみていきます。
1つ目は、キー「url」、値「like.php」です。これは、サーバーのURLとして(Controllersの)like.phpを指定してHTTPリクエストを送るという意味です。
2つ目は、キー「type」、値「POST」です。これは、POSTの形式でHTTPリクエストを送るという意味です。
3つ目は、キー「data」、値はJSON形式のデータです。このようにJSON形式のデータは、JSONの中にJSONを入れ子にすることができます。dataという文字通り、サーバーに送るデータを指定します。キー「like_id」、値「like_id(=変数like_idの値)」というデータをサーバーに送るという意味ですね。JSON形式にしているのは、複数のデータをサーバーに送る場合があるためです。複数のデータを指定する場合は、カンマ区切りでキーと値を並べます。
送られたデータは、サーバー側のPHPでは「$_POST[‘キー名’]」のように取得できます。ここでは「$_POST[‘like_id’]」ですね。

次の「.done(function() { … })」に着目して下さい。
これは「$.ajax()」の処理が終わったら(HTTPリクエストをサーバーに送って、サーバーから応答があったら)、実行される処理という意味です。これは覚えるしかありません。実行される処理は「function(){ … }」の中に書きます。

変更箇所3は、変更箇所2とほぼ同じです。
変更箇所3では、「.done(function(data) { … })」のように、functionの引数に「data」がありますね。これはサーバーからの応答データを指します。これは覚えるしかありません。
サーバー側(Controllers/like.php)の最後に、JSON形式の「$response」をクライアントに返す処理を書きましたね。このJSONデータが「function(data)」のdataに入ってきます。JavaScriptでは、JSON形式のデータは「data[‘キー名’]」のように、PHPの連想配列のように取り出すことができます。ここでは「data[‘like_id’]」として取り出していますね。

ブラウザ

ここまで出来たら、変更内容をコミットし、GitHubにプッシュして下さい。

本節の説明は以上になります。

トップページ <<前のカリキュラムへ戻る 次のカリキュラムへ進む>>

タイトルとURLをコピーしました