ユーザーがオンラインかどうかを知るためにセッションをピギーバックする方法はありますか?
つまり、ログオンを使用し、$ _ SESSION変数を設定し、ユーザーがタイムアウトします。ガベージコレクターがデータベースを更新して、オフラインとしてのステータスを更新します。
EDIT:
時間や日付を含まないソリューションが必要です。セッションなどに乗ってみたいです。誰かがオンラインであるかどうかを推測することは、私が必要とするものに対して十分ではありません。
ユーザーがオンラインかどうかを知るためにセッションをピギーバックする方法はありますか?
つまり、ログオンを使用し、$ _ SESSION変数を設定し、ユーザーがタイムアウトします。ガベージコレクターがデータベースを更新して、オフラインとしてのステータスを更新します。
EDIT:
時間や日付を含まないソリューションが必要です。セッションなどに乗ってみたいです。誰かがオンラインであるかどうかを推測することは、私が必要とするものに対して十分ではありません。
タイムゾーン間の違いをわざわざ理解しないでください。それは必要ありません。
ユーザーがページにアクセスするたびに、Usersテーブルのレコードのフィールドをlast-updated-timeで更新します。次に、過去5分以内に最終更新時刻を持つすべてのユーザーに対してクエリを実行します。これ以上のものは、「オフライン」と見なされます。
MySQLのNOW()関数を使用してサーバー時間を使用する場合は、タイムゾーン間の差の計算を回避します。
これは、現在オンラインになっているユーザーの数を追跡する標準的な方法です(つまり、過去数分以内にアクティブになっています)。
ページ間をジャンプしていなくてもアクティブであることを知りたい場合は、60秒ごとにサーバーにpingを実行するためのJavaScriptを少し含めて、サーバーがまだ生きていることを知らせてください。これは私の最初の提案と同じように機能しますが、少なくとも5分に1回は必死にサイトを閲覧しなくても、レコードを更新します。
var stillAlive = setInterval(function () {
/* XHR back to server
Example uses jQuery */
$.get("stillAlive.php");
}, 60000);
(明確化の後で)あなたが求めていることは、定義上、不可能です。HTTPはコネクションレス型プロトコルであるため、ユーザーがページにアクセスし、すべてのコンテンツがサーバーからユーザーのブラウザーに戻るとすぐに、2つの間に接続はありません。誰かがあなたのウェブサイトに1秒未満「オンライン」になっています。
WebページのJavaScriptで、識別情報を含むAJAXリクエストを定期的にサーバーに返送し、ユーザーがページを離れるときにwindow.onbeforeunloadを使用して別のAJAXリクエストを作成することができます。
私の方法は最善の方法ではないかもしれませんが、私のサイトとユーザーベースはすべてmysql DBにあるため、ユーザーが私のサイトにログインすると、
次に、ページを読み込むたびに、オンラインタイムセッションをチェックします。存在する場合は、その古さを確認します。5分未満の場合は何もしません。5分より古い場合は、更新します。セッション時間を現在の時刻で再度更新し、オンラインユーザーテーブルを時刻で更新します
次に、10〜15分ごとに実行されるcronジョブがあり、オンラインテーブルから使用を削除し、オンライン時間がX分以内に更新された場合にユーザーテーブルをオフラインとしてマークします。
「オンラインの人」の比較ロジックでは、タイムゾーンが考慮されていないようです。この方法でタイムゾーンを処理している場合は、すべての時刻をGMTで保存し、表示する直前にユーザーの現地時間に変換することを強くお勧めします。これにより、比較操作が非常に簡単になります。
ここにタイムゾーンに関する素晴らしいSOスレッドがあります。
私がアドバイスすることの1つは、この種の情報を、たとえばmemcachedまたはmysqlヒープまたはredisを使用してメモリに保存することです。そうしないと、データベースが頻繁にヒットするためです。
タイムゾーンをテーブルに保存し、それを計算に使用して、ページを表示しているユーザーの現地時間と比較して、ユーザーの現地時間を見つけます。
編集:
さらに良いことに、すべての時間をサーバー時間として保存し、すべての計算をサーバー時間のみに基づいて行います。
状況によっては、「ip」列と「last-updated-time」列を含む別のテーブル「whose-online」を作成し、ユーザーがページをロードするたびにこのテーブルをクエリ/更新する方がよい場合があります。
ページの読み込みクエリには、次のものが含まれる場合があります。
この手法を使用する利点:
注:これを使用する場合は、ページビューによってテーブルに行が作成されることを考慮に入れる必要があります。これにより、useragentに基づいて、ボットを無視するか、人気のあるボット(Firefox、IE、Safari、Operaなど)のみをカウントできます。
このために実装した解決策は、認証されたユーザーがページを読み込むたびに、「user_ {userid} isonline」=>trueなどのmemcachevarを設定/リセットし、5分で期限切れにすることです。次に、ユーザーの情報にアクセスするときに、変数がキャッシュにあるかどうかを確認します。ユーザーベースのサイズに応じて、すべてのユーザーのリストをオンラインで取得する場合は、すべてのユーザーの「user{userid}_isonline」キーの配列を使用してmemcachegetmulti呼び出しを使用できます。
もちろん、これは実際にはユーザーがサイトのページを変更する頻度に依存します...オンラインでユーザーをより正確に表現するために、短い間隔(30秒またはつまり、memcache varをリセットし、memcache varの有効期限が短くなります(ブラウザーの問題の可能性を考慮して1分)。これは完全に正確ではありませんが、httpにはサーバーへの永続的な接続がないため、実行できることにはかなり制限があります。
誰がオンラインであるかを2番目まで表現する必要がある場合は、ページにフラッシュアプリをロードして、jabberサーバーに接続し、その特定のユーザーがサーバーにログインしているかどうかを確認することができます。
これは、データベースから2つの日付の差を数分で取得し、差を確認してオンライン/オフラインのステータスを設定する方法です。
$query = 'SELECT * FROM Users';
$result = mysqli_query($mysqli, $query);
foreach($result as $user){
// date from the database
$dbLastActivity = date("d-m-Y h:i:s a", strtotime($user['lastOnline']));
// date now
$now = date("d-m-Y h:i:s a", $date);
// calculate the difference
$difference = strtotime($now) - strtotime($dbLastActivity);
$difference_in_minutes = $difference / 60;
// check if difference is greater than five minutes
if($difference_in_minutes < 5){
// set online status
$updateStatus = 'UPDATE Users SET Status="online" WHERE lastOnline="'.$user['lastOnline'].'"';
} else {
// set offline status
$updateStatus = 'UPDATE Users SET Status="offline" WHERE lastOnline="'.$user['lastOnline'].'"';
}
// check if mysqli query was successful
if (!$mysqli->query($updateStatus)){
printf("Error Message %s\n", $mysqli->error);
}
}
タグを使用することもできますonunload
...本文の詳細はこちら(https://www.w3schools.com/jsref/event_onunload.asp)
このようにして、ユーザーがオフラインになるまで4〜5分待つ必要はありません。
ただし、ユーザーのブラウザがクラッシュした場合に備えて、ajaxupdateメソッドを使用する必要があります...
編集:
@Quentinがコメントで指摘したように、リクエストを送信できない場合がありますが、それを実行する方法はあります...この記事で詳しく説明します。
つまり、基本的にはsendBeacon()を使用しています
。例を次に示します。
window.addEventListener("unload", function logData() {
navigator.sendBeacon("/log", analyticsData);
});
注:これが信頼できる唯一の方法ではなく、冗長性のために実装する必要があることに注意してください...