我正在开发一个“Flash网站”。在这个程序中,我想添加一个依赖于会话的“在线用户”列表:当用户登录时会启动会话,并且用户在数据库中被标记为“在线”。当注销或关闭浏览器时,用户在数据库中被标记为“脱机”。
我知道在浏览器关闭时运行某些功能需要使用Javascript,并且它也不安全:如果浏览器崩溃,则函数将无法运行。这就是为什么如果用户注销或用户的会话超时,我已决定更新数据库。
我一直在寻找会话超时,并遇到了许多其他标记为重复的内容:How do I expire a PHP session after 30 minutes?
答案方法的问题是;这是一个条件句,检查用户的最后一次活动是否是X秒前,如果没有活动,则超时。在某些网站中很有用,但对于在线用户列表没用,因为它在发送新请求时更新,并且因为用户关闭浏览器后不会有任何请求。
在其他答案中也提到使用session.gc_maxlifetime
和session.cookie_lifetime
,但最佳答案指出使用它们是一个坏主意;一个不破坏会话,只破坏cookie,另一个是“成本密集型”。
我想要的是用户超时和数据库更新并将用户标记为离线不使用使用If-Conditional句子,或者可能只使用不同的If条件句子必须在用户登录时使用一次,如计时器或其他东西,每当发送请求时,计时器重新开始......这些只是我到目前为止关于如何解决这个问题的想法。
但是,我该怎么做?如果答案非常简单明了,我很抱歉,我对PHP很新。
编辑:长话短说:
我想在用户关闭浏览器后运行一个功能,或者在20分钟内处于非活动状态。
澄清...
我想在不活动20分钟后更新数据库,即使浏览器已关闭。
答案 0 :(得分:1)
if (!isset($_SESSION['CREATED'])) {
$_SESSION['CREATED'] = time();
} else if (time() - $_SESSION['CREATED'] > 1800) {
// session started more than 30 minutes ago
session_regenerate_id(true); // change session ID for the current session an invalidate old session ID
$_SESSION['CREATED'] = time(); // update creation time
}
还读这个 http://php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime
答案 1 :(得分:1)
您希望使用以下信息来捕获事件: How to capture the browser window close event?
然后,您需要在服务器上使用sessionID调用该事件处理程序中的页面。
该页面调用您设置的本地脚本,页面或服务,以延迟20分钟并使会话到期。如果您想在用户在到期前重新访问时重新启动时钟,则需要包含一种中断或取消该脚本进程的方法,并且您需要将SessionID保留在需要查找的cookie中每页加载。如果找到并匹配cookie的SessionID,则超时被中断/停止(如果它还在继续)。如果已经完成,则需要发布新的SessionID。
如果您同时有很多这些取消,您将在服务器上排队,并让流程定期检查队列并根据需要使它们到期。
大多数网站避免这一切的方式是设置30分钟或任何会话超时,无论访问者是否活跃,都会强制执行。
答案 2 :(得分:1)
我希望在浏览器运行20分钟后更新数据库 闭合。
我认为这不可能与浏览器被关闭(可靠)有关。如果他们单击注销按钮,您显然可以运行一些代码以将用户标记为已注销。您可以使用您提到的功能指定会话有多长时间,但这样做会使cookie在客户端被删除,它不会在服务器端触发任何内容。
关于你唯一可以做的就是跟踪用户上次活动的时间,以及他们是否在一段时间内没有活动,假设他们已经离开了。因此,只需在用户表中添加一个字段,并存储其上一个活动的日期时间或unix时间戳。然后,您可以每隔几分钟运行一次cron作业,将用户标记为已注销,或者您只需修改SQL查询即可仅提取最后一次活动少于20分钟的用户。
答案 3 :(得分:1)
您可以借助具有最后活动字段的在线用户表
来完成此操作window.setInterval(function() {
$.ajax({
url: "http://yourdomain/updateLastactive/?uid=" + User_ID,
success: function(data) {
}
});
}, 5000); // 5 seconds
此页面将更新当前时间戳作为该用户的最后一个活动
然后在线用户查询,您可以执行以下操作,
SELECT UID FROM ONLINE_USERS WHERE LAST_ACTIVE > DATE_SUB(NOW(), INTERVAL 30 MINUTE));
答案 4 :(得分:0)
执行此操作的最简单方法是编写一个查看会话时间戳的MySQL存储过程,并在会话数据为>时删除会话数据。 20分钟。您也可以将其作为外部cron作业,但存储过程会更好。
此外,每次用户连接时都需要刷新会话时间戳。
如果您想确保在用户仍然打开“页面”时不删除会话,那么一些后台JavaScript刷新到您的站点将充当保持活动状态。请注意,如果用户关闭“窗口”或“标签”,它将与整个浏览器关闭相同 - 我不确定您是否可以对此做任何事情。
当然,要执行此操作,您需要将会话存储在MySQL中。
TL; DR