質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

2回答

788閲覧

リアルタイムチャットでのスマホの入室者カウントについて

nosonosolife

総合スコア42

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

0クリップ

投稿2019/07/20 01:18

編集2019/07/25 13:45

JavaScriptとPHPでリアルタイムチャットを製作しているのですが、どうやって現在の入室者数をカウントするかで嵌っています。

入室者数を記録するファイルを用意して、入室したらPHP側で1足して、退室したら1引く、とすればいいんですが、
問題は途中でページを離脱した際の処理です。
チャットには「退室ボタン」を用意するつもりですが、押さずに別のページに移行するユーザーもいます。
そういう時は、パソコンならJavaScriptの「beforeunload」でPHPにデータを送信して、
途中でページを離脱した際でも退室扱いにする事が出来ます。
しかし、スマホ・タブレット用の「pagehide」では、同じタブ(ウィンドウ)でページ移行したり、ページを更新した際にはイベントが実行されるのですが、タブを閉じた際には実行されないのです。
そうなると、もしユーザーが「退室ボタン」を押さずにタブを閉じた際、入室者数に誤差が発生することになります。

これをなんとか解決したいのですが、どうすればいいでしょうか?
ご提示よろしくお願いいたします。

==2019/07/25 追記==
mikkameさん、mts10806さんから頂いたヒントから、自分なりに考えてコードを組んでみました。

php

1session_id(sha1(uniqid(microtime())));

まずチャットにアクセスした際に、セッションIDを作成しておきます。

javasctipt

1function chatOnline(){ 2 $.ajax({ 3 type: "post", 4 url: "php/usercount.php", 5 data: { Penname: userName }, 6 timeout: 10000, // 単位はミリ秒 7 8 success: function(result, textStatus, xhr) { 9 onlineTimer = setTimeout( "chatOnline()", 10000 ); 10 }, 11 // 通信失敗時の処理 12 error: function(xhr, textStatus, error) { 13 14 } 15 }); 16} 17 $.ajax({ 18 url: 'php/usercount.php', 19 type: 'GET', 20 dataType: 'json', 21 data: {ut: (new Date().getTime())} 22 }) 23 .done(function(result) { 24 if(result){ 25 $("hoge").html('現在の入室者数:' + result[0].usercount + '人'); 26 } 27 });

javasctiptで10秒ごとにPHPにデータを送信します。

PHP

1<?php 2session_start(); 3if($_SERVER["REQUEST_METHOD"] == "POST"){ 4 mb_language("uni"); 5 mb_internal_encoding("utf-8"); //内部文字コードを変更 6 mb_http_input("auto"); 7 mb_http_output("utf-8"); 8 9 date_default_timezone_set('Asia/Tokyo'); 10 11 if(isset($_POST['Penname'])){ 12 $json = file_get_contents('../data/log/userlog.json'); 13 $records = json_decode($json, true); 14 15 $Id = session_id(); 16 $Penname = htmlspecialchars($_POST["Penname"]); 17 $Time = time(); 18 19 $result_index = array_keys(array_column($records, 'id'), $Id); 20 21 if($result_index == null){ 22 $records[] = [ 23 'id' => $Id, 24 'time' => $Time, 25 'penname' => $Penname, 26 ]; 27 }else{ 28 foreach ($records as $key => $value) { 29 $nowtime = $Time; 30 $lasttime = $value['time']; 31 if(($nowtime - $lasttime) > 60){ 32 unset($records[$key]); 33 }else{ 34 foreach ($result_index as $index) { 35 $records[$index]['time'] = $Time; 36 } 37 } 38 } 39 } 40 41 $out_json = json_encode($records); 42 43 $result = file_put_contents("../data/log/userlog.json", $out_json, LOCK_EX); 44 } 45} 46if($_SERVER["REQUEST_METHOD"] == "GET"){ 47 $json = file_get_contents('../data/log/userlog.json'); 48 $records = json_decode($json, true); 49 $Num = count($records); 50 $usercount[] = [ 51 'usercount' => $Num, 52 ]; 53 54 echo json_encode($usercount); 55} 56?>

PHPでは、リクエストがPOSTの場合は、ユーザー別にセッションIDや最終アクセス時間などをファイルに記録します。
最終アクセス時間が1分を過ぎても変更されない場合、ファイルからデータを削除します。
リクエストがGETの場合は、現在の入室者数を返します。
以上です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takasima20

2019/07/20 01:22

ブラウザ使ってる限りムリじゃないかな?
hentaiman

2019/07/23 17:18

> flag 質問者が42分前に「まだ回答を求めています」と言っています。 もう回答してあるけど、Server-Sent Eventsだけでやりたいなら無理
退会済みユーザー

退会済みユーザー

2019/07/24 01:15

これ以上どんな回答を求めているのでしょうか?
m.ts10806

2019/07/24 01:57

mikkameさんの回答で充分解決可能です。(私も同じ方法を思いつきました) キーワードも出ているので探して何もコードのヒントが得られない内容ではないですよ。
nosonosolife

2019/07/24 02:52

直近のリクエストの取得の仕方とか、判定の仕方とか、 もう少し詳細な解説が欲しかったのです。 どうしても書き方が思いつかなくて。
guest

回答2

0

ベストアンサー

古典的な方法ですが、phpで行うなら、クライアントより、定期的(1秒毎とか)にリクエストを送信させ
直近のアクセスがあるクライアントをオンラインとし
アクセスがなくなったアカウントをオフラインとするとかですかね。
server sent eventを使う意味がほぼ無くなりますが

投稿2019/07/20 17:07

mikkame

総合スコア5036

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nosonosolife

2019/07/22 07:09

ご回答ありがとうございます。 コードなども記載していただけると幸いです。
mikkame

2019/07/22 13:01

ここは作業依頼をするところではありませんよ。 コードを書いて欲しいのであれば、対価の支払いを要求します。 crowsworksやlancersへどうぞ。
nosonosolife

2019/07/24 02:54 編集

直近のリクエストの取得の仕方とか、判定の仕方とか、 もう少し詳細な解説をよろしくお願いいたします。
m.ts10806

2019/07/24 02:59

別途回答をつけるほどでもないと思うのでこちらにぶら下がらせていただきますが、 リアルタイムチャットということは定期実行されているわけですよね。 定期実行するときにAjaxで新規コメントとかをとってきているような仕組みだとしたら そのコメントをとってきているタイミングで、「最終アクセス時間」みたいなのを更新するような仕組みにすると、その「最終アクセス時間が更新されない=オフラインになった」と判断できる ということになると思います。
nosonosolife

2019/07/24 07:44

>mts10806さん その「最終アクセス時間」の更新をどうやって判定するのか、 またアクセス時間はユーザー別に記録するのかなども教えていただけると幸いです。
m.ts10806

2019/07/24 07:47

>「最終アクセス時間」の更新をどうやって判定するのか、 判定は必要ないです。 最終アクセス時間を更新できるのはあくまで「今チャットルームをブラウザで開いているユーザー」なので。 もちろん現在アクティブかどうかはユーザー毎に見るのでユーザー別に記録しないと意味がありません。
mikkame

2019/07/24 07:48

最終アクセス時間をユーザー別にデータベースに記録して行けば良いです。 目的を達成するにはどのようなデータがあれば実現できるか考えれば必然とわかるはずです。 例)年齢を表示したい → 生年月日か、年齢が必要
m.ts10806

2019/07/24 07:50

nosonosolifeさん このままやりとりを続けていても我々から実コードは出てきませんし、 考え方および設計・実装する上でのヒントは十分出ているものと思いますので、 一旦ここは引いて、ここまでの回答・コメントから考えて自身でやってみてください。
m.ts10806

2019/07/24 07:52

mikkameさんの例に考え方を追加 年齢を表示したい → 生年月日か、年齢が必要 ↓ 年齢だけだと毎年足していかないといけない ↓ 生年月日のみ登録して年齢は現在日時から年齢を計算する
nosonosolife

2019/07/25 12:27

先ほど質問文に、頂いたヒントから考えたコードを追記いたしました。
guest

0

Server-Sent Eventsでは多分無理
websocketなら多分できる

https://www.ibm.com/developerworks/jp/web/library/wa-http-server-push-with-websocket-sse/index.html

投稿2019/07/20 01:43

hentaiman

総合スコア6389

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問