学習内容を備忘録としてまとめます。
メッセージ機能を実装しましたので、作成方法を記載します。
ユーザー同士でメッセージ機能を用いてやり取りすることができます。
実装方法
実装方法について記載していきます。
テーブル構成
messaegeテーブル
とmessage_relationテーブル
の2つを作成します。
各カラムは下記のような役割を担っています。
カラム名 | 役割 |
---|---|
id | メッセージID |
text | メッセージ内容 |
image | メッセージに添付される画像 |
user_id | メッセージをしたユーザーID |
destination_user_id | メッセージ送信先のユーザーID |
created_id | メッセージをした時刻 |
メッセージ画面
実際にメッセージのやり取りが行われる、メッセージ画面について実装していきます。
<?php
$current_user = get_user($_SESSION['user_id']);
$destination_user = get_user($_GET['user_id']);
$messages = get_messages($current_user['id'], $destination_user['id']);
?>
<body>
<div class="message">
<h2 class="center"><?= $destination_user['name'] ?></h2>
<?php foreach ($messages as $message) :?>
<div class="my_message">
<?php if ($message['user_id'] == $current_user['id']) : ?>
<div class="mycomment right">
<span class="message_created_at"><?= convert_to_fuzzy_time($message['created_at']) ?></span><p><?= $message['text'] ?></p><img src="../user/image/<?= $current_user['image'] ?>" class="message_user_img">
</div>
<?php else : ?>
<div class="left"><img src="../user/image/<?= $destination_user['image'] ?>" class="message_user_img">
<div class="says"><?= $message['text'] ?></div><span class="message_created_at"><?= convert_to_fuzzy_time($message['created_at']) ?></span>
<?php endif; ?>
</div>
<?php endforeach ?>
<div class="message_process">
<h2 class="message_title">メッセージ</h2>
<form method="post" action="../message/message_add.php" enctype="multipart/form-data">
<textarea class="textarea form-control" placeholder="メッセージを入力ください" name="text"></textarea>
<input type="hidden" name="destination_user_id" value="<?= $destination_user['id'] ?>">
<div class="message_btn">
<div class="message_image">
<input type="file" name="image" class="my_image" accept="image/*" multiple>
</div>
<button class="btn btn-outline-primary" type="submit" name="post" value="post" id="post">投稿</button>
</div>
</form>
</div>
</div>
</body>
23行目の<?php endforeach ?>
までが、メッセージのやり取りが表示されている箇所で、
それ以降はメッセージを入力するフォーム等が記載されています。
<?php
$current_user = get_user($_SESSION['user_id']);
$destination_user = get_user($_GET['user_id']);
$messages = get_messages($current_user['id'], $destination_user['id']);
?>
こちらはメッセージをやり取りする上で必要な情報を取得しています。
それぞれ下記のような役割を担っています。
変数名 | 役割 |
---|---|
$current_user | 現在ログインしているユーザー情報 |
$destination_user | メッセージ送信先のユーザー情報 |
$messages | やり取りされるメッセージ情報 |
get_user
、get_messages
関数で情報を取得しています。
function get_user($user_id){
try {
$dsn='mysql:dbname=db;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);
}
}
function get_messages($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 *
FROM message
WHERE (user_id = :id and destination_user_id = :destination_user_id) or (user_id = :destination_user_id and destination_user_id = :id)
ORDER BY created_at ASC";
$stmt = $dbh->prepare($sql);
$stmt->execute(array(':id' => $user_id,
':destination_user_id' => $destination_user_id));
return $stmt->fetchAll();
} catch (\Exception $e) {
error_log('エラー発生:' . $e->getMessage());
set_flash('error',ERR_MSG1);
}
}
それぞれテーブルからユーザーID
と送信先ユーザーのID
を引数にして情報を取得しています。
$sql = "SELECT *
FROM message
WHERE (user_id = :id and destination_user_id = :destination_user_id) or (user_id = :destination_user_id and destination_user_id = :id)
ORDER BY created_at ASC";
ユーザーによってはユーザー情報が互い違いになっているため、
WHERE
条件でIDが取得できるようにしています。
$destination_user = get_user($_GET['user_id']);
送信先ユーザーについては、URLからIDを取得しています。
<a href='message.php?user_id=<?= $destination_user['id'] ?>'>
このようにURLから送信先ユーザーID
を取得しています。
続いてメッセージのやり取りを表示するブラウザ画面をみてきます。
<?php foreach ($messages as $message) :?>
<div class="my_message">
<?php if ($message['user_id'] == $current_user['id']) : ?>
<div class="mycomment right">
<span class="message_created_at"><?= convert_to_fuzzy_time($message['created_at']) ?></span><p><?= $message['text'] ?></p><img src="../user/image/<?= $current_user['image'] ?>" class="message_user_img">
</div>
<?php else : ?>
<div class="left"><img src="../user/image/<?= $destination_user['image'] ?>" class="message_user_img">
<div class="says"><?= $message['text'] ?></div><span class="message_created_at"><?= convert_to_fuzzy_time($message['created_at']) ?></span>
<?php endif; ?>
</div>
<?php endforeach ?>
自分のメッセージと送信先のメッセージが表示されるようになっています。
<?php foreach ($messages as $message) :?>
先ほどget_messages
関数で取得したメッセージ情報をforeach文でループ処理します。
<?php if ($message['user_id'] == $current_user['id']) : ?>
<div class="mycomment right">
<span class="message_created_at"><?= convert_to_fuzzy_time($message['created_at']) ?></span><p><?= $message['text'] ?></p><img src="../user/image/<?= $current_user['image'] ?>" class="message_user_img">
</div>
<?php else : ?>
<div class="left"><img src="../user/image/<?= $destination_user['image'] ?>" class="message_user_img">
<div class="says"><?= $message['text'] ?></div><span class="message_created_at"><?= convert_to_fuzzy_time($message['created_at']) ?></span>
<?php endif; ?>
メッセージ表示部分をみていきます。
自分と送信先のユーザーメッセージによって、左右に表示させるためにif文で分岐させています。
メッセージテーブルには送信したユーザーIDのカラムがあるので、そちらで判断しています。
messageの各カラムをブラウザに表示させています。
メッセージのレイアウトは下記を参照させていただきました。
また、convert_to_fuzzy_time
関数では取得した時刻情報から表示形式を渡しています。
詳細は下記の参照をお願いします。
メッセージ送信フォームについてみていきます。
<div class="message_process">
<h2 class="message_title">メッセージ</h2>
<form method="post" action="../message/message_add.php" enctype="multipart/form-data">
<textarea class="textarea form-control" placeholder="メッセージを入力ください" name="text"></textarea>
<input type="hidden" name="destination_user_id" value="<?= $destination_user['id'] ?>">
<div class="message_btn">
<div class="message_image">
<input type="file" name="image" class="my_image" accept="image/*" multiple>
</div>
<button class="btn btn-outline-primary" type="submit" name="post" value="post" id="post">投稿</button>
</div>
</form>
</div>
</div>
コメント内容の記載と画像を添付できるようになっており、
message_add.php
に遷移しコメントテーブルにINSERTをかけるような処理になっています。
※上記のコードは説明上不要な部分を省略しているので、トップの動作画面とは違いがあります。
<input type="hidden" name="destination_user_id" value="<?= $destination_user['id'] ?>">
送信先のユーザーIDを渡しています。
これでメッセージテーブルの中に相手側の情報をもつことができます。
では、先ほど説明したmessage_add.php
についてみていきます。
メッセージ処理
<?php
try
{
$date = new DateTime();
$date->setTimeZone(new DateTimeZone('Asia/Tokyo'));
$message_text=$_POST['text'];
$message_image=$_FILES['image'];
$user_id=$_SESSION['user_id'];
$destination_user_id = $_POST['destination_user_id'];
if($message_text=='')
{
set_flash('danger','メッセージ内容が未記入です');
reload();
}
if($message_image['size']>0)
{
if($message_image['size']>1000000)
{
set_flash('danger','画像が大きすぎます');
reload();
}
else
{
move_uploaded_file($message_image['tmp_name'],'./image/'.$message_image['name']);
}
}
$message_text=htmlspecialchars($message_text,ENT_QUOTES,'UTF-8');
$user_id=htmlspecialchars($user_id,ENT_QUOTES,'UTF-8');
$dsn = 'mysql:dbname=db;host=localhost;charset=utf8';
$user = 'root';
$password = '';
$dbh = new PDO($dsn,$user,$password);
$dbh -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = 'INSERT INTO message(text,image,user_id,destination_user_id,created_at) VALUES (?,?,?,?,?)';
$stmt = $dbh -> prepare($sql);
$data[] = $message_text;
$data[] = $message_image['name'];
$data[] = $user_id;
$data[] = $destination_user_id;
$data[] = $date->format('Y-m-d H:i:s');
$stmt -> execute($data);
$dbh = null;
if(!check_relation_message($user_id,$destination_user_id)){
insert_message($user_id,$destination_user_id);
}
set_flash('sucsess','メッセージを送信しました');
header('Location:../message/message.php?user_id='.$destination_user_id.'');
}
catch (Exception $e)
{
print'ただいま障害により大変ご迷惑をお掛けしております。';
exit();
}
?>
<a href="post_index.php">戻る</a>
メッセージ内容と添付されている画像を確認して、メッセージテーブルにINSERTしています。
if(!check_relation_message($user_id,$destination_user_id)){
insert_message($user_id,$destination_user_id);
}
こちらではcheck_relation_message
関数で、message_relation
テーブルに自分のIDと送信先ユーザーのIDがあるかどうか確認しています。
今回は関数の前に!
マークがついているので、あればfalse
なければture
になります。
function check_relation_message($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 user_id,destination_user_id
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)";
$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
と送信先ユーザーID
の組み合わせがmessage_relation
テーブルにあるかどうか確認しています。
insert_message($user_id,$destination_user_id);
true
である場合には、insert_message
関数で引数の自分のユーザーID
と送信先のユーザーID
を元にrelation_message
テーブルにINSERT
しています。
後ほど説明しますが、message_relation
テーブルとはメッセージ一覧画面で使用されるテーブルであり、
メッセージのやりとりがあったユーザーに関しては、このテーブルにIDが格納されます。
メッセージ一覧画面
上記動作画面のように、メッセージでやりとりのあったユーザーを表示し一覧化する画面となっています。
テーブルについてはテーブル構成
で説明したmessage_relationテーブル
を使用します。
メッセージ一覧画面で使用されるmessage_top.php
をみていきます。
<?php
$current_user = get_user($_SESSION['user_id']);
$message_relations = get_message_relations($current_user['id']);
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']);
?>
<body>
<div class="row">
<div class="col-8 offset-2">
<a href='message.php?user_id=<?= $destination_user['id'] ?>'>
<div class="destination_user_list">
<img src="../user/image/<?= $destination_user['image']?>" class="message_user_img">
<div class='destination_user_info'>
<div class="destination_user_name"><?= $destination_user['name']?></div>
<span class="destination_user_text"><?= $bottom_message['text'] ?></span>
</div>
<span class="bottom_message_time"><?= convert_to_fuzzy_time($bottom_message['created_at']); ?></span>
</div>
</a>
</div>
</div>
<?php endforeach ?>
</body>
message_relation
テーブルからメッセージのやりとりがあるユーザー情報を取得して、一覧画面にユーザーの名前、アイコン画像等を表示しています。
$message_relations = get_message_relations($current_user['id']);
get_message_relations
関数で引数の自分のユーザーID
からメッセージのやりとりがあるユーザー情報を取得しています。
function get_message_relations($user_id){
try {
$dsn='mysql:dbname=db;host=localhost;charset=utf8';
$user='root';
$password='';
$dbh=new PDO($dsn,$user,$password);
$sql = "SELECT *
FROM message_relation
WHERE user_id = :user_id";
$stmt = $dbh->prepare($sql);
$stmt->execute(array(':user_id' => $user_id));
return $stmt->fetchAll();
} catch (\Exception $e) {
error_log('エラー発生:' . $e->getMessage());
set_flash('error',ERR_MSG1);
}
}
引数のユーザーIDから取り出します。
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']);
}
送信先のユーザーID
を取得しています。
メッセージを送信するときにmessage_relation
テーブルにINSERT
されるので、
ユーザーによってはmessage_relation
テーブルの自分のユーザーID
と送信先のユーザーID
が互い違いになっている可能性があるため、if文で条件分岐させています。
$bottom_message=get_bottom_message($current_user['id'],$destination_user['id']);
メッセージ一覧を表示する際に、やりとりの最後のメッセージを表示させるため、get_bottom_message
関数でメッセージ情報を取得しています。
function get_bottom_message($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 *
FROM message
WHERE (user_id = :user_id and destination_user_id = :destination_user_id)
or (user_id = :destination_user_id and destination_user_id = :user_id)
ORDER BY created_at DESC";
$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
と送信先のユーザーID
から作成時間の一番古いメッセージを取得しています。
<div class="row">
<div class="col-8 offset-2">
<a href='message.php?user_id=<?= $destination_user['id'] ?>'>
<div class="destination_user_list">
<img src="../user/image/<?= $destination_user['image']?>" class="message_user_img">
<div class='destination_user_info'>
<div class="destination_user_name"><?= $destination_user['name']?></div>
<span class="destination_user_text"><?= $bottom_message['text'] ?></span>
</div>
<span class="bottom_message_time"><?= convert_to_fuzzy_time($bottom_message['created_at']); ?></span>
</div>
</a>
</div>
</div>
あとは、一覧画面に必要なメッセージ情報をブラウザに表示させています。