【第2回】PHPでチャット機能の作り方!ユーザー切り替えの分岐と適切な終了処理

【第2回】PHPでチャット機能の作り方!ユーザー切り替えの分岐と適切な終了処理

この記事からわかること

  • ユーザーを切り替えたフラグの生成
  • ユーザーを切り替えた時のデータ格納の分岐
  • チャットログのリセット機能
  • Topページに戻るときにセッションを破棄

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

第1回:【自作】PHPでチャット機能の作り方!LINEのような会話形式のプログラムのコードを徹底解説!

前回でチャット機能の根幹部分は完成しました!以下のコードが前回の作成分です。


<?php   
$J_file = "chatlog.json"; // ファイルパス格納
date_default_timezone_set('Asia/Tokyo'); // タイムゾーンを日本にセット

// ここに新しいコードを記述

if(isset($_POST['submit']) && $_POST['submit'] === "送信"){ // #1
    
    // ここに新しいコードを記述
    $chat = [];
    $chat["person"] = "person1";
    $chat["imgPath"] = "image/person1.png"; //画像ファイル名は任意
    $chat["time"] = date("H:i");
    $chat["text"] = htmlspecialchars($_POST['text'],ENT_QUOTES);

    // 入力値格納処理
    if($file = file_get_contents($J_file)){ // #2
      // ファイルがある場合 追記処理
      $file = str_replace(array(" ","\n","\r"),"",$file);
      $file = mb_substr($file,0,mb_strlen($file)-2);
      $json = json_encode($chat);
      $json = $file.','.$json.']}';
      file_put_contents($J_file,$json,LOCK_EX);
    }else{ // #2
      // ファイルがない場合 新規作成処理
      $json = json_encode($chat);
      $json = '{"chatlog":['.$json.']}';
      file_put_contents($J_file,$json,FILE_APPEND | LOCK_EX);
    } // #2

    // header('Location:https://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/chat.php');
    header('Location:./chat.php');
    exit;   

  } // #1

if($file = file_get_contents($J_file)){
  $file = json_decode($file);
  $array = $file->chatlog;
  foreach($array as $object){
        if(isset($result)){
            // 第二回目以降
            $result =  $result.'<div class="'.$object->person.'"><p class="chat">'.str_replace("\r\n","<br>",$object->text).'<span class="chat-time">'.$object->time.'</span></p><img src="'.$object->imgPath.'"></div>';
        }else{
            // 第一回目
            $result = '<div class="'.$object->person.'"><p class="chat">'.str_replace("\r\n","<br>",$object->text).'<span class="chat-time">'.$object->time.'</span></p><img src="'.$object->imgPath.'"></div>';
        }
} 
}

// ここに新しいコードを記述
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0">
  <title>チャット</title>
  <link rel="stylesheet" href="css/style.css">
  <link rel="stylesheet" href="css/fontawesome-free-5.15.3-web/css/all.min.css">
  <script src="js/main.js"></script>
</head>
<body>
  <main class="main">
  <div class="chat-system">

  <!-- ここに新しいコードを記述 -->

    <div class="chat-box">
      <div class="chat-area" id="chat-area">
        <?php echo $result; ?>
      </div>
      <form class="send-box flex-box" action="chat.php#chat-area" method="post">
      <textarea id="textarea" type="text" name="text" rows="1" required placeholder="message.."></textarea>
        <input type="submit" name="submit" value="送信" id="search">
        <label for="search"><i class="far fa-paper-plane"></i></label>
        </form>
    </div>
  </div>

  <!-- ここに新しいコードを記述 -->

  </main>
</body>
</html>

今回はチャット機能を1人でも楽しめるようにユーザーを切り替えられるようにしていきたいと思います。

ユーザー切り替え分岐

まず最初にHTML部分を記述していきます。chat-systemの中にタイトルとメッセージ、そしてユーザー切り替え用のフォーム部分を追加しておきます。


<div class="chat-system">
  <h2 class="text-center"><i class="far fa-comments"></i></h2>
  <p class="text-center">1対1のチャット機能です。下のユーザーを切り替えることで会話が楽しめます。</p>
  <form method="get" action="chat.php">
        <div class="change-person flex-box">
          <input type="submit" id="person2" name="person" value="person2"><label for="person2"><img  class="<?php if($_SESSION['person'] === 'person2'){echo "on";}?>" src="image/person2.png"></label>
          <input type="submit" id="change" name="change" value="change"><label for="change"><i class="fas fa-people-arrows"></i></label>
          <input type="submit" id="person1" name="person" value="person1"><label for="person1"><img class="<?php if($_SESSION['person'] === 'person1'){echo "on";}?>" src="image/person1.png"></label>
      </div>
  </form>
  <div class="chat-box">
   // 最初のフォームエリア(textareaなど)
  </div>
</div>

チャット入力のフォーム部分と同じくinput要素label要素をidとforでリンクさせておき、typeは全てsubmitにしておくことで押したボタンだけの値(value属性)が格納されます。

そしてPOSTではなくURLからでもユーザーがどちらか識別できるようにGETでの値の受け渡しにしておきます。

またクラス属性にonがあるかないかでHTML表示の切り替えの指標にします。onがある方のみ色を変えることでどちらに切り替わっているか識別できるようにしています。

onをつけるか付けないかは$_SESSION['person']に格納されている値で判断します。後ほどセッションを使用するので今はコードの流れだけ理解しておいてください。

この章のポイント

これでアクティブになっているユーザー名が$_GET['person']に格納されています。切り替えはユーザーアイコンをクリックするか中央のチェンジアイコンをクリックするかで切り替えできるようにしています。

ユーザー切り替えのフラグ

GETに格納されたユーザー名をチャットを送信したりリロードした時にリセットされないようにGETやPOSTではなくSESSIONに格納しておきます。つまりセッションに入っている値がアクティブになっているべきユーザー名ということになります。


<?php
$J_file = "chatlog.json";
date_default_timezone_set('Asia/Tokyo');
// 以下追加
session_start(); 

// ユーザーアイコンが押された時
if(isset($_GET['person'])){
  $_SESSION['person'] = $_GET['person'];

}else{

  // ユーザーアイコンも押されず、切り替えアイコンも押されていない時(=初めてページに訪れた時)
  if(empty($_GET['change']) && empty($_SESSION['person'])){
    $_SESSION['person'] = 'person1';
    // 以下切り替えアイコンが押された時にアクティブのユーザーではない方に切り替える処理
  }elseif ($_GET['change'] === 'change' && $_SESSION['person'] === "person2"){
    $_SESSION['person']  = 'person1';//現在2なら1をアクティブに
  }elseif($_GET['change'] === 'change' && $_SESSION['person'] === "person1"){
    $_SESSION['person']  = 'person2';//現在1なら2をアクティブに
  }
}

セッションを使用する際はまずセッションが使えるようにスタートさせないといけないのでファイルの上部にコードを付け加えておきます。(5行目)

関連記事:【php】SESSION(セッション)とcookie(クッキー)の違いは?メリットと仕組みを徹底解説!

その下に$_GET['person']に値が格納されていれば(ユーザーアイコンが押されていれば)フラグ(セッション)に追加する処理を記述しておきます。(8,9行目)

そして新規にページに訪れた時はユーザー1に、チェンジが押された時はアクティブになっているユーザーの反対をフラグの中に格納しておきます。(14~21行目)

ユーザーによるデータ格納の分岐

続いてアクティブになっているユーザーに応じてJSONファイルに格納するデータも変更しないといけません。現在はチャットを送信すると問答無用でユーザー1にしていましたがセッションの値によって格納するデータを分岐させます。


if(isset($_POST['submit']) && $_POST['submit'] === "送信"){ // #1

  if($_SESSION['person'] === 'person1'){
    $chat = [];
    $chat["person"] = "person1";
    $chat["imgPath"] = "image/person1.png";
    $chat["time"] = date("H:i");
    $chat["text"] = htmlspecialchars($_POST['text'],ENT_QUOTES);
  }elseif( $_SESSION['person'] === 'person2'){
    $chat = [];
    $chat["person"] = "person2";
    $chat["imgPath"] = "image/person2.png";
    $chat["time"] = date("H:i");
    $chat["text"] = htmlspecialchars($_POST['text'],ENT_QUOTES);
  }

最初のデータ格納の部分に$_SESSION['person']の値による分岐処理を入れ込みます。

変更部分は$chat["person"]$chat["imgPath"]の値です。それ以外は同じなのでifの外に書いても良いかもしれません。

チャット履歴をクリア

チャット機能のデモページのためチャット履歴を削除できるようにしておきます。

JSONファイルの中身を空にするだけで良いのでボタンが押されたら空にする処理を行います。

まずはボタンをページ上に作りましょう。chat-systemグループの外側に新しくフォームエリアを作り、その中にボタンを2つ生成しておきます。


 </div> 
  <!-- chat-system終わり -->  
  <form action="chat.php" method="GET">
    <input class="btn back-btn" type="submit" name="back" value="Topページに戻る">
    <input class="btn back-btn" type="submit" name="reset" value="チャット履歴をリセット">
  </form>
</main>

1つはTopページに戻るボタンです。a要素でのジャンプでも良いですが、セッションの破棄を行わないといけないので戻るボタンが押されたらセッションを破棄してheader関数でリダイレクト処理でTopページに戻しています。

関連記事:セッションの破棄の仕方

2つ目がチャット履歴をクリアするボタンです。ボタンが押されたらfile_put_contents関数を利用してデータを空白で上書きしています。空にしたら自分自身へリダイレクトさせてチャット履歴の表示もクリアにしておきます。

関連記事:【php】ファイルの中身を空にする方法を解説!サイズをゼロにして削除しよう!


if($_GET['reset'] === "チャット履歴をリセット" && isset($_GET['reset'] )){
  file_put_contents($J_file,'');
  // header('Location:https://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/chat.php');
  header('Location:./chat.php');
  exit;   
}

if($_GET['back'] === "Topページに戻る" && isset($_GET['back'] )){

  $_SESSION = [];
  if(isset($_COOKIE[session_name()])){
  $params = session_get_cookie_params();
  setcookie(session_name(), '', time() - 42000, $params["path"],$params["domain"],$params["secure"],$params['httponly']);
  }
  session_destroy();
  header("Location:../index.php");
  exit;   
}
?>
<!DOCTYPE html>

ユーザー切り替え時にCSSも変化

最後にbodyにユーザー識別用のクラスを付与してチャットの表示をCSSで整えます。CSSはもう記述済みですが、アクティブのユーザーのチャット履歴を右側に、相手側のユーザーを左側に表示されるようにしておきます。


<body class="<?php if($_SESSION['person'] === 'person2'){echo "second";}?>">

ユーザー1の時のCSS表示

自作チャットのユーザー1の時のCSS

ユーザー2の時のCSS表示

自作チャットのユーザー2の時のCSS

最後に

これで全ての工程が終了しました。どうしても正常に動かない場合は気軽にお問い合わせください。どのような相談でも必ず返信いたします。

追記:2021/10/17

Ajax機能を使ってチャットログの自動更新機能を追加しました!

第3回:【Ajax】チャットログを自動更新して表示させる方法!phpとjavascriptで実装

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index