ゴールデンウィークは台湾出張中で仕事をしなければならないので、土日を使って子供に算数を教える事になった。
そのためにはリモートで子供とコミュニケーションを取る必要がある。
ZOOM、Teams、LINE ……と考えてみたけど、子供が使い慣れているTeamsが良さそうだ。
ただTeamsは互いに社内/校内アカウントで利用しており、(おそらく)常時チャットで連絡をとることができない。
チャットできないと会話する時間を合わせる事もできないので、別途チャットを作成することにした。
結果的にLINEによく似たチャットとなった。
PHPでLINE風チャット実装
まずはググったら同じことをしている人を発見した。
内容を公開してくれているのは嬉しいが、ソースコードが断片的になっている。
全部Github上に載せたら良いのにな。
そのまま使おうかと思ったが
次のような実装を追加した。
- 全体的にグレー色なのでLINE風に変更
- チャットのユーザ切り替えがボタンだったのでURLによる切り分けに変更
- 「既読」機能の追加
- スマホ向けレスポンシブルデザイン
- 画像表示機能(添付はできない)
え?私のLINEなの?
でも、左右で吹き出しの色って違うんだよ。
なるほど、対応。
「既読」が無いよ?
マジカヨ。
「既読」機能って難しいんだよ。
ChatworkやSlackも付けてない。これ実装都合もあると思う。
仕方ないので
- 最終アクセス/最終画面更新時間を保存
- それより古い相手の投稿に「既読」をマークする
という対応にした。
毎回「既読」チェックが走るし、PHP側で処理しているのでサーバ負荷もかかる。
投稿数が増えてくると処理が追いつかない気がする……。
でも完成。
「https://アドレス/?man=1」と「https://アドレス/」にアクセスすると互いにコミュニケーションが取れるようになっている。
スタンプ機能は?
画像送れないの?
連絡来たら通知機能は無いの?
……そこまで無理。
画像だけならAjaxとPHPで転送できるが、LINEのように画像と文字を一緒にAjaxで送る方法は見つからなかった。
所定のフォルダに画像を別途SFTPで送ることで、表示することは可能にしておいたけど……。
連絡通知も「Push.js」を使えばポップは出ることは確認したけど、そもそも相手がブラウザを閉じてたら、ブラウザ上でしか動作しないので何もできない。
おわりに
相方から
「子供がお父さんからの連絡をずっと待ってパソコンを何度も開きに行く」
との連絡があった。
……やっぱそうなるよね。
ソースコード
基本的には前述したサイトのソースコードを丸写し。
だったけど、chatlog.phpとindex.phpのコードに重複箇所が多いのでまとめた。
GitHubはここ。
【index.php】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
<?php // 変更箇所 ==================================== // fontawesomeのファイル置き場 $FONTAWESOME = 'fontawesome-free-6.4.0-web'; // 1人目のアイコン $PERSON1 = 'image/person1.png'; // 2人目のアイコン $PERSON2 = 'image/person2.png'; //============================================== include('common.php'); // 共通部分の分離 date_default_timezone_set('Asia/Tokyo'); // タイムゾーンを日本にセット file_put_contents($PUT_t_file, date('Y/m/d H:i'), LOCK_EX); if (isset($_POST['submit']) && $_POST['submit'] === '送信') { // #1 $chat = []; $chat['person'] = 'person1'; $chat['imgPath'] = $PERSON1; if ($_GET['man']) { $chat['person'] = 'person2'; $chat['imgPath'] = $PERSON2; } $chat['time'] = date('Y/m/d H:i'); $chat['text'] = htmlspecialchars($_POST['text'], ENT_QUOTES); $pattern = '/((?:https?|ftp):\/\/[-_.!~*\'()a-zA-Z0-9;\/?:@&=+$,%#]+)/'; $replace = '<a target="_blank" href="$1">$1</a>'; $chat['text'] = preg_replace($pattern, $replace, $chat['text']); // 入力値格納処理 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); // 時間保存 file_put_contents($PUT_t_file, $chat['time'], LOCK_EX); } else { // #2 // ファイルがない場合 新規作成処理 $json = json_encode($chat); $json = '{"chatlog":['.$json.']}'; file_put_contents($J_file, $json, FILE_APPEND | LOCK_EX); // 時間保存 file_put_contents($PUT_t_file, $chat['time'], LOCK_EX); } // #2 header('Location:./index.php?'.$_SERVER['QUERY_STRING']); exit; } // #1 // ファイルサイズが違った時 if ($file = file_get_contents($J_file)) { $result = output_message($file, $GET_t_file); // 現在のファイルサイズと旧ファイルサイズを表示 $result = $result.'<input id="preFilesize" type="hidden" value="'.$_SESSION['filesize'].'"><input id="aftFilesize" type="hidden" value="'.$filesize.'">'; } else { // チャット履歴がない場合はチャットが増えたときに備える $result = '<input id="preFilesize" type="hidden" value="'.$_SESSION['filesize'].'"><input id="aftFilesize" type="hidden" value="'.$filesize.'">'; } ?> <!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>LINE風チャット</title> <link rel="stylesheet" href="css/style.css?<?php echo date('Ymd-Hi'); ?>"> <link rel="stylesheet" href="<?php echo $FONTAWESOME; ?>/css/all.min.css"> <script src="js/main.js"></script> </head> <body class="<?php if($_GET['man']){echo "second";}?>"> <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="<?php 'echo index.php?' . $_SERVER['QUERY_STRING']; ?>#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> |