【问题标题】:Whats the easiest way to determine if a user is online? (PHP/MYSQL)确定用户是否在线的最简单方法是什么? (PHP/MYSQL)
【发布时间】:2010-11-06 07:37:52
【问题描述】:

有没有办法可以通过会话来了解用户是否在线?

即:使用登录,我设置了一个 $_SESSION 变量,用户超时 - cookie 垃圾收集器更新数据库以将其状态更新为离线。

EDIT:我想要一个不涉及时间或日期的解决方案。我想要一些东西来参加会议或类似的事情。猜测某人是否在线不足以满足我的需求。

【问题讨论】:

  • 基于“last_activity_time”的跟踪或基于过期会话的跟踪对于准确告诉您有多少用户“在线”并不重要。主要区别在于您可以在大约 5 分钟内实现第一种方法。后一种方法需要您不断检查所有会话(对于所有用户......哎哟)并处理它们的值 - 呸。
  • 不幸的是,我必须清楚地知道用户是否连接到该站点。
  • @Mike,看看我附加的解决方案。
  • 如果我的理解是正确的。在线用户意味着,他的会话在服务器中持续存在。所以如果我们将会话保存在数据库表中而不是文件中,我们可以轻松计算对吗?

标签: php javascript mysql offline


【解决方案1】:

将时区存储在表中,并在计算中使用它来查找用户本地时间与查看页面的用户本地时间的比较。

编辑:

更好的是,将所有时间存储为服务器时间,并将所有计算仅基于服务器时间。

【讨论】:

    【解决方案2】:

    听起来您的“是在线人”比较逻辑没有考虑时区。如果您以这种方式处理时区,我强烈建议您将所有时间存储在 GMT 中,并在显示它们之前将它们转换为您的用户的本地时间。这将使任何比较操作都变得非常简单。

    有一个关于时区的不错的 SO 线程 here

    【讨论】:

    • 格林威治标准时间 +1。第二好的是使用服务器时间。但是,如果您需要跨时区移动服务器,那会破坏您的所有历史数据。在 GMT 中存储日期时间要好得多。 Server Time 也适用于仅从单个位置(如办公室)访问的内部数据库。但即使是办公室也可以移动。
    【解决方案3】:

    不必费心弄清楚时区之间的差异。没必要。

    每当用户访问页面时,更新用户表上次更新时间记录中的字段。然后查询所有在过去 5 分钟内具有最后更新时间的用户。除此之外,它们都被视为“离线”。

    如果您使用服务器时间,通过 MySQL 中的 NOW() 函数,您将避开计算时区之间的差异。

    这是跟踪当前在线用户数量的标准方法(意思是在最后几分钟内活跃)。

    不断更新

    如果您想知道即使它们没有从一个页面跳转到另一个页面,它们仍然处于活动状态,请添加一些 javascript 以每 60 秒左右对您的服务器执行一次 ping 操作,以让您知道它们仍然处于活动状态。它的工作方式与我最初的建议相同,但它会更新您的记录,而无需他们至少每五分钟疯狂浏览一次您的网站。

    var stillAlive = setInterval(function () {
        /* XHR back to server
           Example uses jQuery */
        $.get("stillAlive.php");
    }, 60000);
    

    【讨论】:

    • 我已经在一大堆类似问题的网站中游荡,你是第一个给出满意答案的人。非常感谢。
    • 你会在数据库中的时间戳上放一个索引吗?
    • 另一个简单的答案:stackoverflow.com/questions/24402047/…
    • 我正在考虑在我自己的网站上使用这种方法,但是评论部分 /* XHR 回到服务器示例使用 jQuery */ 让我有点困惑,这是否只是执行一个更新的 php 脚本用户每 60 秒在数据库中看到的最后一次时间?我在任何地方都找不到有关此功能的信息。
    【解决方案4】:

    根据您的情况,您最好创建一个单独的表“whose-online”,其中包含以下列:“ip”和“last-updated-time”,并在每次用户加载时查询/更新此表一个页面。

    页面加载查询可能包括

    1. 根据 ip 为当前用户更新/插入“whose-online”表。
    2. 删除“过期”行(也可以使用 cronjob 定期完成)。
    3. 统计“活跃”用户。

    使用这种技术的好处

    1. 如果用户未登录,他/她仍会被统计/跟踪。
    2. 取决于您拥有的用户数量,查询此表可能会更快。

    注意:如果你使用它,你应该考虑到任何页面浏览都会在你的表格中创建一行,因此基于用户代理你可以忽略机器人或只计算流行的机器人(Firefox、IE、Safari、Opera 等) )。

    【讨论】:

      【解决方案5】:

      根据定义,您所要求的(在澄清之后)是不可能的。 HTTP 是一种无连接协议,因此一旦用户点击了一个页面,并且所有内容都从服务器返回到用户的浏览器,两者之间就没有任何连接。有人在您的网站上“在线”不到一秒钟。

      可以做的一件事是让您的网页上的 JavaScript 定期向您的服务器发送 AJAX 请求,其中包括识别信息以及用户离开页面时的不同 AJAX 请求,使用 window.onbeforeunload

      【讨论】:

      • 这个浏览器事件'onbeforeunload'非常棒,但是当用户的互联网连接丢失并且他关闭浏览器标签时它不起作用
      【解决方案6】:

      我建议的一件事是将此类信息存储在内存中,例如 memcached 或 mysql heap 或 redis。因为否则数据库会受到很大的打击。

      【讨论】:

        【解决方案7】:

        我为此实施的解决方案是,在经过身份验证的用户加载每个页面时,设置/重置 memcache var,例如“user_{userid}isonline”=> true 并在 5 分钟内过期.然后在我访问用户信息时检查 var 是否在缓存中。根据您的用户群的大小,如果您想获取在线所有人的列表,您可以使用 memcache getmulti 调用和所有用户的“user{userid}_isonline”键数组。

        当然,这实际上取决于用户更改您网站上页面的频率...为了更准确地表示在线用户,您可以在您的页面上实现一个 ajax xmlhttprequest 调用,以小间隔运行( 30 秒左右)重置 memcache var,并让 memcache var 在更短的时间内过期(1 分钟以解决可能的浏览器问题)。这并不完全准确,但由于 http 没有与服务器的持久连接,因此您可以做的事情非常有限。

        如果您需要最多第二个表示谁在线,您可能会在您的页面中加载一个连接到 jabber 服务器的 flash 应用程序,然后只需检查该特定用户是否已在服务器上登录。

        【讨论】:

          【解决方案8】:

          我的方式可能不是最好的方式,但由于我的网站和用户群都在 mysql DB 中,当用户登录我的网站时,

          1. 我更新用户表说他们 在线
          2. 将它们插入在线表格中
          3. 然后我与 当前时间

          然后在每次页面加载时,我都会检查在线时间会话,如果存在,我会检查它的年龄,如果小于 5 分钟,我什么也不做,如果大于 5 分钟,然后我用当前时间再次更新会话时间,并用时间更新在线用户表

          然后我有一个每 10 到 15 分钟运行一次的 cron 作业,它会从在线表中删除任何使用情况,如果在线时间在 X 分钟内更新,则将用户表标记为离线

          【讨论】:

            【解决方案9】:

            你也可以在body上使用onunload标签... 更多信息在这里 (https://www.w3schools.com/jsref/event_onunload.asp)

            这样您不必等待 4 -5 分钟让用户下线。

            但是你仍然应该使用 ajax 更新方法以防用户的浏览器崩溃......

            编辑: 正如@Quentin 在 cmets 中指出的那样,您可能无法发送请求,但有一种方法可以做到...... 在this Article中有更详细的解释。
            所以基本上他们使用的是sendBeacon() 这是一个例子

            window.addEventListener("unload", function logData() {
              navigator.sendBeacon("/log", analyticsData);
            });
            

            注意:虽然应该记住,这不应该是您应该依赖的唯一方法,并且应该实现冗余......

            【讨论】:

            • 在 onunload 中向服务器发送消息是 IIRC 不可能的(因为请求在页面卸载时被取消)。如果用户因为关闭计算机、进入没有移动信号的隧道等而停止在线,它也不会起作用。
            • @Quentin 我们仍然可以使用sendBeacon() 解释here
            • 如果用户因为关闭计算机、进入没有移动信号的隧道等而停止在线,则否
            【解决方案10】:

            这是一种如何在几分钟内从数据库中获取两个日期之间差异的方法,然后检查差异并设置在线/离线状态。

            $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);
                }
            } 
            

            【讨论】:

            • 你用 20 行 PHP 而不是 1 行 SQL 来做这件事,因为....原因?
            • 很好奇在 1 行中看到这段代码 :) 给我看。我说了我做了什么。
            • SELECT * FROM Users WHERE last_active &gt;= (NOW() - interval '5 minutes')
            • 或者对于整个shebang... sql:SELECT * FROM Users WHERE last_active &gt;= (NOW() - interval '5 minutes')set_active.php:pg_query_params($conn, "UPDATE Users SET last_active=NOW() WHERE user_id=$1", [$_GET['user_id']]);`heartbeat.js:setInterval(() =&gt; { fetch('last_active.php?user_id=' + userID }, 60000)
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-05-01
            • 2012-03-14
            • 2013-08-22
            • 1970-01-01
            • 2011-01-13
            相关资源
            最近更新 更多