ツイート一覧取得機能の作成
ツイートモデルの変更
tweets.phpを以下のように修正します。
htdocs/Twitter/Models/tweets.php
<?php
// 設定ファイルの読み込み
include_once '../config.php';
// ツイート登録関数
function createTweet(array $data)
{
// データベースに接続
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
// 成功/失敗確認
if ($mysqli->connect_errno) {
echo 'MySQLの接続に失敗しました。<br>';
exit;
}
// ツイート登録のSQLを作成
$query = 'INSERT INTO tweets (user_id, body, image_name) VALUES (?, ?, ?)';
// セキュリティ上、以下のように書く
$statement = $mysqli->prepare($query);
$statement->bind_param('iss', $data['user_id'], $data['body'], $data['image_name']);
// SQLを実行
$response = $statement->execute();
// 成功/失敗確認
if ($response == false) {
echo 'エラーが発生しました。<br>';
}
// データベースへの接続解除
$statement->close();
$mysqli->close();
// result変数には、true(成功)or false(失敗)が入っている
return $response;
}
// ★変更箇所(ここから)
function getTweets($user)
{
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
// 成功/失敗確認
if ($mysqli->connect_errno) {
echo 'MySQLの接続に失敗しました。<br>';
exit;
}
// ログインしているユーザーのユーザーIDを取得
$user_id = $user['id'];
// ツイート一覧を取得するSQLを作成
$query = <<<SQL
SELECT
tweets.id AS tweet_id,
tweets.status AS tweet_status,
tweets.body AS tweet_body,
tweets.image_name AS tweet_image_name,
tweets.created_at AS tweet_created_at,
users.id AS user_id,
users.name AS user_name,
users.nickname AS user_nickname,
users.image_name AS user_image_name,
likes.id AS like_id,
(SELECT COUNT(*) FROM likes WHERE status = 'active' AND tweet_id = tweets.id) AS like_count
FROM
tweets
INNER JOIN users
ON users.id = tweets.user_id AND users.status = 'active'
LEFT JOIN
likes
ON likes.tweet_id = tweets.id AND likes.status = 'active' AND likes.user_id = '$user_id'
WHERE
tweets.status = 'active'
SQL;
// SQLを実行
$result = $mysqli->query($query);
// 成功/失敗確認
if ($result == false) {
echo 'エラーが発生しました。<br>';
$mysqli->close(); // データベースへの接続解除
return false;
}
// ツイート一覧を取得
$tweets = $result->fetch_all(MYSQLI_ASSOC);
$mysqli->close();
return $tweets;
}
// ★変更箇所(ここまで)
?>
まずは「$query = <<<SQL … SQL;」の箇所から解説します。
一度に複数行のSQLを書きたい場合、「<<<SQL」と「SQL」で囲んだ部分にSQLを書くことができます。PHPはその部分をSQLの文字列と認識してくれます。
文字列をダブルクォーテーションで囲んだ場合と同様、その中に変数を含めれば、その値を抽出してくれます。ここでは、$user_idが含まれており、$user_idの値(1など)が取り出されて、「likes.user_id = ‘1’」のようになるわけです。
「<<<SQL」と「SQL」の中に書かれたSQLを見ていきます。
「SELECT * FROM テーブル名」は以前解説しました。
今回は「SELECT ~ FROM ~ WHERE ~」となっています。
WHEREは条件です。「WHERE ~」は、「~という条件に合致したデータのみを取得する」という意味になります。
「SELECT ~ FROM ~ WHERE ~」は、①「FROM ~」 ②「WHERE ~」 ③「SELECT ~」の順に実行されます。①~③の内容を順にみていきます。
「FROM ~」は、「~で指定したテーブルからデータを取得する」という意味でした。
まずは「tweets」が指定されていますね。
次に「INNER JOIN users」と書かれています。直訳すると、「(tweetsテーブルと)usersテーブルを内部結合する」という意味になります。文字通り、テーブルどうしを結合して1つのテーブルにするということで、下図のイメージになります。
次の「ON users.id = tweets.user_id AND users.status = ‘active’」は結合条件になります。「usersテーブルのid(ユーザーID)の値と、tweetsテーブルのuser_idの値が等しい」場合のみテーブルを結合する、という意味になります。下図のイメージになります。
かつ、「users.status = ‘active’」条件により、usersテーブルのstatusカラムの値が「active」のデータのみが抽出されます。
さらに「LEFT JOIN」と書かれており、その結合条件として「likes.tweet_id = tweets.id AND likes.status = ‘active’ AND likes.user_id = ‘$user_id’」が指定されています。
「LEFT JOIN」もテーブルの結合を指しますが、「LEFT」とあるように「左側のテーブルのデータはすべて残す」という意味になります。下図のイメージになります。
かつ、「likes.status = ‘active’ AND likes.user_id = ‘$user_id’」の結合条件が指定されています。下図のイメージになります。
以上が「FROM ~」内で行われていることです。
次に「WHERE ~」内が実行されます。「tweets.status = ‘active’」は、tweetsテーブルのstatusカラムの値が「active」のデータのみを取得する、という意味ですね。
よって、上図の(結合前のtweetsテーブルのstatusの値が)activeであれば、当該データを取得できることになります。逆にactiveでなければ、当該データは取得できません。
最後に、「SELECT ~」内が実行されます。
「*」は、テーブルの全カラムの値を取得する、という意味になります。
一方、特定のカラム名を書くと、そのカラムの値のみを取得することができます。
例えば、「SELECT name from users」と書くと、usersテーブルのnameカラムの値だけが取得できます。複数カラムの値がほしい場合は、カンマ区切りで複数書きます。
ここでは「tweets.id」のようなカラムの指定の仕方をしています。
これは「tweetsテーブルのidカラム」を指定している、という意味になります。
「テーブル名.」を付けているのは、少し下に「users.id」があるためです。tweetsテーブルもusersテーブルも、同じカラム名の「id」をもっています。このような場合は、どちらのテーブルかを示すために、「テーブル名.」で教えてあげているのです。
「tweets.id AS tweet_id」とは何でしょうか。
これは、tweets.idを、別名の「tweet_id」というカラム名にリネームして取得する、という意味になります。ASを直訳すると「~として」なので、カラム名を「tweet_idとして(取得する)」ということですね。
次に「(SELECT COUNT(*) FROM likes WHERE status = ‘active’ AND tweet_id = tweets.id) AS like_count」に着目して下さい。「SELECT COUNT(*) FROM likes WHERE status = ‘active’ AND tweet_id = tweets.id」を括弧()で囲うことで一括りの処理としており、その処理結果を、like_countカラムの値としています。
では、「SELECT COUNT(*) FROM likes WHERE status = ‘active’ AND tweet_id = tweets.id」は何でしょうか。
「FROM likes WHERE status = ‘active’」の部分は、likesテーブルのデータ、かつstatusカラムの値が「active」であるデータ、という意味でしたね。
次の「tweet_id = tweets.id」に着目して下さい。
tweet_idはlikesテーブルのカラムです。tweets.idはtweetsテーブルの(ツイート)IDです。likesテーブルにあるtweet_idと同じ値を、tweetsテーブルから探しています。
「COUNT(*)」は数をカウントしてくれるデータベースが持つ関数です。すなわち、「likesテーブルにあるtweet_idと同じ値を、tweetsテーブルから探して、その数をカウントする」という意味になります。その値をlike_countとしています。
「SELECT ~」内が実行された結果、以下のような形でデータを取得できます。
SQLの実行および成否確認は以前解説した通りです。
「$tweets->fetch_all(MYSQLI_ASSOC)」でSQLの実行結果を、配列として取得して変数$tweetsに入れています。fetch_all関数はPHPの関数、MYSQLI_ASSOCはPHPの変数です。
ホームコントローラーの変更
ホームコントローラーを以下のように修正します。
htdocs/Twitter/Controllers/home.php
<?php
include_once '../util.php';
// ★変更箇所1(ここから)
// ツイートモデルを読み込み
include_once '../Models/tweets.php';
// ★変更箇所1(ここまで)
// ログインチェック
$view_user = getSession();
if ($view_user == false) {
// ログインしていない
header('Location: ../Controllers/sign-in.php');
exit;
}
// ★変更箇所2(ここから)
// ツイート一覧取得
$view_tweets = getTweets($view_user);
// ★変更箇所2(ここまで)
// 画面表示
include_once '../Views/home.php';
?>
変更箇所1では、「include_once ‘../Models/tweets.php’」により、tweets.phpファイルを読み込んでいます(埋め込んでいます)。これにより、同ファイル内のgetTweets関数が使えるようになります。
変更箇所2では、getTweet関数を呼び出して、ツイート一覧を取得しています。
引数には、セッションのユーザー情報を渡しています。
取得したツイート一覧($view_tweets)は、Views/home.phpの中で使われることになります。
ツイート領域の変更
ツイート領域を以下のように修正します。
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-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>
微調整を行っています。
ログインすると、ホーム画面に投稿したツイートが表示されることを確認して下さい。
ここまで出来たら、変更内容をコミットし、GitHubにプッシュして下さい。
本節の説明は以上になります。