使用PHP显示在线用户列表

4

大家好,我有部分工作代码。但是我也遇到了一些问题。让我先告诉你我想要实现什么... 在我的网站上,我有一个登录设施,只有当用户登录后才能将所有用户发送到主页。我想在我的页面上显示谁还在登录,并以列表形式显示他们的用户名。

我的代码当前能力...

好的,所以我可以编写代码将加入网站的用户添加到数据库中,然后将该数据库中的每个用户显示到一个div中,这非常棒,因为它显示了所有在线的人...

问题所在...

然而,当用户离开页面时,他们的用户名需要从在线用户数据库中删除。过去,我会使用java的on window close选项来完成此操作。但由于Google Safari和Firefox不再支持此选项,我被迫寻找另一种方法来完成它。

以下代码的功能...

因此,下面的代码加载一个间隔,所以经过一段时间后它将重复其中的代码。代码首先将用户添加到数据库中,然后在网站上显示用户列表,最后从数据库中删除用户,以防万一他们下线。

问题所在...

对于一个用户来说,这一切都很好,但是一旦第二个用户参与进来,它们的间隔时间就不同了。所以我已经从数据库中删除了用户,但这意味着第二个用户显示数据库时,第一个用户不在其中,因为他们被删除了...这也会导致问题,如果一个用户在函数进行一半的时候离线了,那么它会将其留在数据库中,并且无法将其从数据库中删除。

以下是Java代码...

    $(document).ready(function() {
   
var user_name = "<?php print $username ?>";

setInterval(function() {

       $.post('onlineusers.php', { name: user_name, action:"joined" }); 

       $.post("onlineusers.php", { action2: "list" }, function(data){
       $('#listusers').html(data);
       });

       $.post("onlineusers.php", { nameleft: user_name, action3:"left" }, function(data){
       $('#errorrreport').html(data);
       });

}, 5000);
           
    }):  
    

现在有PHP文档代码。
    //------------User joined page put into database --------  
if( $_REQUEST["name"])
{
  $user_name = $_REQUEST['name'];
};  

if( $_REQUEST["action"])
{
  $action = $_REQUEST['action'];  
};

if ($action == 'joined') {
  user_joined($user_name);   
};

//-----------Listing online users within page -------------  
 if( $_REQUEST["action2"])
{
  $action2 = $_REQUEST['action2'];

};

if($action2 == 'list') {

foreach (user_list() as $user){
       echo $user . "<br />";  
      
};
};

//------------ User left delete from the database ------------
if( $_REQUEST["nameleft"])
{
  $user_nameleft = $_REQUEST['nameleft'];

};  

if( $_REQUEST["action3"]){
  $action3 = $_REQUEST['action3'];
};

if($action3 == 'left') {
  user_left($user_nameleft); 
};        



//------ Functions what to do... --------

    function user_joined($user_name) {
  $user_name = mysql_real_escape_string(htmlentities($user_name));
  mysql_query("INSERT INTO users (user_name)VALUES('$user_name')") or die("this didn't happen");
   
}

function user_left($user_nameleft) {
  $user_name = mysql_real_escape_string(($user_nameleft));
  $query = mysql_query("DELETE FROM users WHERE user_name = '$user_nameleft'")or die("failed to delete from table");

}

function user_list() {
  $user_list = array();
  $users_query = mysql_query("SELECT user_name FROM users") or die ("Unable to collect userlist");
  
while ($users_row = mysql_fetch_assoc($users_query)){
  $user_list[] = $users_row['user_name'];

}  
   
  return $user_list;

}

上述代码

抱歉有点凌乱,因为我反复编码以使其正常工作。如果有人能帮助我让它正常工作,我会非常感激。现在,如果这不仅仅是上面代码的问题,我可以在页面进入时将用户添加到在线用户数据库,并通过列出数据库中的用户经常性地获取在线用户列表。

下面是实际问题,请求您的帮助...

然而,如果您有任何关于以下代码的想法,那就太好了... 用户离开页面时会出现问题。 我需要一些方法来检查用户是否仍处于活动状态,如果他们没有,则从数据库中删除他们,以便在列表刷新时,该用户不再在列表中。 比如不断发出ping直到没有响应并删除用户数据。

由于我的当前代码存在多个用户和间隔函数同步的问题,它需要考虑到不同的用户将在不同的时间看到列表刷新。

P.S.我也尝试过使用$SESSION,但仍然不确定如何检查离线用户并将它们从数据库中删除,这可能是一种方法。

谢谢,希望有足够的信息可以继续。


我曾经在以前尝试过这个,Chrome/Firefox支持得很好,我认为它仍然支持,在JavaScript事件上工作,如果用户关闭选项卡,它会将其从列表中删除,但是Opera没有内置此事件处理程序,虽然计划了多年,但Opera正在消亡,我不认为它会有一天出现。那么实现这个的方法是将每个用户操作记录到数据库中,并记录时间,如果时间比30秒旧,则不从在线用户列表中选择此用户。这在每个浏览器上都可以正常工作。 - Wiggler Jtag
但是问题来了:如果它是一个聊天系统,例如用户只是阅读消息而没有执行任何操作,那么存在一个很棒的jQuery空闲插件,可以跟踪用户鼠标事件:http://www.paulirish.com/2009/jquery-idletimer-plugin/,它的效果非常好,我一直在使用它来显示聊天中的空闲/活动用户。 - Wiggler Jtag
2个回答

2

我采取了不同的方法:
JS:
每隔5秒循环一次,在linenow.php上发送AJAX请求,并在在线用户框中显示返回的html,这主要是从W3C复制并粘贴而来,其中URL已更改。

setInterval("getOnline()",5000);
function getOnline()
{
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.getElementById("onlineNow").innerHTML=xmlhttp.responseText;
    }
  }
xmlhttp.open("GET","http://www.path.com/to/onlinenow.php",true);
xmlhttp.send();
}

PHP:
获取用户/IP/标识符并将其与Unix时间戳存储/更新到数据库中
返回过去10分钟内Unix时间戳的所有行的列表

<?php
header('Access-Control-Allow-Origin: *');//Pretty sure this enables cross domain AJAX
$session = $_SERVER['REMOTE_ADDR'];
$time=time();
$time_check=$time-60; //SET TIME 10 Minute


$host="localhost"; // Host name
$username="root"; // Mysql username
$password="pass"; // Mysql password
$db_name="custom"; // Database name
$tbl_name="table"; // Table name


// Connect to server and select databse
 mysql_connect("$host", "$username", "$password")or die("cannot connect to server");
 mysql_select_db("$db_name")or die("cannot select DB");

// Check if user is already in the DB
$sql="SELECT * FROM $tbl_name WHERE session='$session'";
 $result=mysql_query($sql);

$count=mysql_num_rows($result);

if($count=="0"){
    //User is not in the DB, lets add them
$sql1="INSERT INTO $tbl_name(session, time, ip)VALUES('$session', '$time', '".$_SERVER['REMOTE_ADDR']."')";
$result1=mysql_query($sql1);
}
//Update this user's entry
else {
    //User is in the DB, Update their entry
    $sql2="UPDATE $tbl_name SET time='$time' WHERE session = '$session'";
    $result2=mysql_query($sql2);
}

//Done updating info, time to get the user list
// if over 10 minute, delete session - Could just get all in past 10 mins instead
$sql4="DELETE FROM $tbl_name WHERE time<$time_check";
$result4=mysql_query($sql4);

//Get total users (Could get a list of names if you preferred and store the info)
$sql3="SELECT * FROM $tbl_name";
$result3=mysql_query($sql3);
$count_user_online=mysql_num_rows($result3);
if ($count_user_online == 1) {
    $plur = "";
}
else {
    $plur = "s";
}
echo "&nbsp;&nbsp;$count_user_online user".$plur." online now&nbsp;&nbsp;";

// Close connection 
mysql_close();
 ?>

我曾多次使用这个逻辑,有时候会显示用户名(有时只是一个数字)。


当然,代码可以改进,但基本原则已经是一个相当不错的解决方案了。


是的,这很有道理,可能会很有用,请展示一些代码,以便我可以借鉴它的逻辑以备将来使用,谢谢 :) - Wiggler Jtag
抱歉代码可能有点乱,我已经有一段时间没有进行更改了,但它可以工作! - Stephen Smith
非常感谢Stephen,我只是在尝试混合一些东西。我并不是说这就是答案,因为我想看看其他几种方法,因为了解别人的做法总是有助于找到最佳方法。 - user2784179

0
你可以尝试在插入时包含一个时间戳(基于服务器),而不是删除。
然后让JavaScript代码每隔一分钟左右进行插入/更新。
那么,你查询谁在线的方式就是查找最近时间戳(比如最近65秒)的行。
当然,你最终需要清除表中的旧行,除非你想要记录每个人何时上线。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接