在 php 会话超时时更新数据库 table
update database table on session timeout in php
我有一个如下所示的 php 代码,当没有 activity 时,会话超时发生在 60 分钟后。以下代码在文件 /mno.php 中。我的登录和注销code也在同一个文件/mno.php中。
/mno.php
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 3600)) {
session_destroy(); // destroy session data in storage
!isset($_SESSION['pageadmin']);
/* Update Table (START) */
$open="false";
$stmt= $connect->prepare("UPDATE trace_users SET open=? WHERE user_name=?");
$stmt->bind_param('ss', $open, $_SESSION['user_name']);
$stmt->execute();
/* Update Table (END) */
header('location: /mmo.php');
exit();
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
代码中的tabletrace_users跟踪所有登录用户。在那个 table 中,有两列 user_name 和 open。当任何用户 log in/log out.
时,该值设置为 true/false
我已经包含了 sql 查询,当没有 activity 但不幸的是 列时,我试图在其中更新 table当 60 分钟没有 activity 发生时,该特定用户 的值未设置为 false。
这是我试过的:
经过一些研究,我想我必须 运行 一个计时器 (js/ajax)。在下面显示的 javascript 中,我计算了 上次 Activity 和 当前时间 之间的差异。
如果超过 60 分钟,那么它将更新数据库 table。这是我尝试过的方法,但我认为需要做更多工作才能更新数据库中的 table。
<script>
let x = setInterval(function() {
let lastActivity = <?php echo ($_SESSION['LAST_ACTIVITY']); ?>
let now = <?php echo time() ?>;
let difference = now - lastActivity;
if (difference > 3600) {
clearInterval(x);
}
}, 1000
);
</script>
问题陈述:
我想知道我应该对上面的 js(或 php)代码进行哪些更改,以便在 60 分钟内没有 activity 时,它应该更新列 open 到 false(在 table trace_users 中)。
编辑 1:
我的登录代码和会话历史代码在同一个文件中/mno.php。我已将所有内容放在同一个文件 /mno.php 中。
这是网页的简单时间验证:
$modified_on = isset($SERVER['HTTP_IF_MODIFIED_SINCE']) ? $SERVER['HTTP_IF_MODIFIED_SINCE'] : null;
$current_time = time();
if (!is_null($modified_on) && ($current_time - strtotime($modified_on)) > 3600) {
session_destroy();
...
}
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $current_time).' GMT');
...
我想你知道这段代码
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 3600)) {
//...
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
在每个请求上运行,仅在请求到达时运行
想象一下,我访问了您的网站,然后在浏览器打开的情况下出去购物。你认为会发生什么?
NOTHING - 因为不会有新的请求发送给你(假设你没有实施任何定期 ajax 轮询/Websocket 机制)
所以服务器不会理我,直到我购物回来刷新页面,服务器才会意识到"Hmmm..This guy's LAST_ACTIVITY is older than an hour let me update my trace_users
table and set open as false
for him"
来到你提出的解决方案,它看起来不错并且避免了 websockets/periodic ajax 请求的复杂性
只需要一些小的更正,请按照此处进行基本演示
<script>
var lastActivity = <?php echo ($_SESSION['LAST_ACTIVITY']); ?>; //the timestamp of latest page refresh or navigation
//This will remain constant as long as page stays put
var now = <?php echo time() ?>; //This takes inital value (technically same as LAST_ACTIVITY) from server
// but later on it will be incremented by javascript to act as counter
var logoutAfter = 5; //I set 5 sec for demo purposes
var timer = setInterval(function() {
now++;
let delta = now - lastActivity;
if ( delta > logoutAfter) {
alert('you are logged out');
clearInterval(timer);
//DO AJAX REQUEST TO close.php
}
}, 1000);
</script>
这里的 lastActivity
将保存页面由服务器发送到浏览器时的时间戳,它永远不会被浏览器上的脚本更改,
now
是您的计数器,您将使用它来跟踪自页面加载到浏览器以来经过了多少时间,您将每秒递增它并检查是否已超过给定的时间量
如果 true 执行 ajax 请求(或简单地重定向到 logout.php),您将在其中销毁会话并更新 trace_users
table 以将用户标记为已关闭
更新
所以ajax会像
$.ajax({
url: "/close.php",
type: 'POST', // GET also fine
data: { },
success: function(data) {
window.location.href= '/mmo.php';
},
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus);
}
});
和
close.php
<?php
session_start();
$logoutAfter = 5; //5 sec timeout for testing purposes
// I'm not sure whether the below if condition check is required here or not
// because we have already checked (whether to timeout or not ) in our javascript
// and we call close.php only when it's affirmative
// I encourage you to test and find out :)
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > $logoutAfter)) {
session_destroy(); // destroy session data in storage
!isset($_SESSION['pageadmin']);
/* Update Table (START) */
$open="false";
$stmt= $connect->prepare("UPDATE trace_users SET open=? WHERE user_name=?");
$stmt->bind_param('ss', $open, $_SESSION['user_name']);
$stmt->execute();
/* Update Table (END) */
//header('location: /mmo.php'); //<-- no need of it when url hit by ajax
exit();
}
else //<-- note the else
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
我认为 Vineys 和 jo0gbe4bstjbs 的回答是错误的,因为当用户关闭浏览器直到 5 秒时,它无法在 60 分钟和会话后更新 table。会话在 php.ini 配置文件中设置的时间后立即删除。
你介意每 5 秒请求一次是解决这个问题的好方法吗?这对性能来说是最糟糕的。
如果你想专业地解决这个问题,你应该添加 "last_request" 列并从 table 中删除 "open" 列,并且在每个请求之后你应该将 last_requests 值更新为当前的 unix 时间戳.在获取用户的地方你应该写:
$time = time() - 3600;
"SELECT * FROM `users` WHERE last_request > $time" //active users
"SELECT * FROM `users` WHERE last_request <= $time" //inactive users
而不是 ajax 每 5 秒请求一次,你应该写 setTimeout 3600 秒延迟时间 运行 window.location.href= '/mmo.php';代码。
如果您想要最佳性能并在 60 分钟注销后获得准确结果,这很好
Page.php
<!-- CODE TO INCLUDE IN HEADER.PHP -->
<?php
session_start();
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
?>
<!-- CLOSE -->
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
</head>
<body>
</body>
<script>
let lastActivity = <?php echo ($_SESSION['LAST_ACTIVITY']); ?>; //the timestamp of latest page refresh or navigation
//This will remain constant as long as page stays put
let now = <?php echo time() ?>; //This takes inital value (technically same as LAST_ACTIVITY) from server+
// but later on it will be incremented by javascript to act as counter
let logoutAfter = 5; //I set 5 secs for demo purposes
let timer = setInterval(function() {
now++;
let delta = now - lastActivity;
if ( delta > logoutAfter) {
alert('you are logged out');
clearInterval(timer);
//DO AJAX REQUEST TO close.php
$.ajax({
url: "/mmo.php",
type: 'POST', // GET also fine
data: { },
success: function(data) {
},
error: function(jqXHR, textStatus, errorThrown) {
console.log("I am inside error");
alert(textStatus);
}
});
}
}, 1000); //<-- you can increse it( till <= logoutAfter ) for better performance as suggested by @"Space Coding"
</script>
</html>
mmo.php
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
$connect = new mysqli($servername, $username, $password, $dbname);
if ($connect->connect_error) {
die("Connection failed: " . $connect->connect_error);
}
session_start();
$logoutAfter = 5; //5 sec timeout for testing purposes
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > $logoutAfter)) {
session_destroy(); // destroy session data in storage
!isset($_SESSION['pageadmin']);
/* Update Table (START) */
$open="false";
$stmt= $connect->prepare("UPDATE trace_users SET open=? WHERE user_name=?");
$usname = !empty($_SESSION['user_name'])?$_SESSION['user_name']:'';
$stmt->bind_param('ss', $open, $usname );
$stmt->execute();
/* Update Table (END) */
//header('location: /mmo.php'); //<-- no need of it when url hit by ajax
exit();
}
else //<-- note the else
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
?>
我有一个如下所示的 php 代码,当没有 activity 时,会话超时发生在 60 分钟后。以下代码在文件 /mno.php 中。我的登录和注销code也在同一个文件/mno.php中。
/mno.php
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 3600)) {
session_destroy(); // destroy session data in storage
!isset($_SESSION['pageadmin']);
/* Update Table (START) */
$open="false";
$stmt= $connect->prepare("UPDATE trace_users SET open=? WHERE user_name=?");
$stmt->bind_param('ss', $open, $_SESSION['user_name']);
$stmt->execute();
/* Update Table (END) */
header('location: /mmo.php');
exit();
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
代码中的tabletrace_users跟踪所有登录用户。在那个 table 中,有两列 user_name 和 open。当任何用户 log in/log out.
时,该值设置为 true/false我已经包含了 sql 查询,当没有 activity 但不幸的是 列时,我试图在其中更新 table当 60 分钟没有 activity 发生时,该特定用户 的值未设置为 false。
这是我试过的:
经过一些研究,我想我必须 运行 一个计时器 (js/ajax)。在下面显示的 javascript 中,我计算了 上次 Activity 和 当前时间 之间的差异。 如果超过 60 分钟,那么它将更新数据库 table。这是我尝试过的方法,但我认为需要做更多工作才能更新数据库中的 table。
<script>
let x = setInterval(function() {
let lastActivity = <?php echo ($_SESSION['LAST_ACTIVITY']); ?>
let now = <?php echo time() ?>;
let difference = now - lastActivity;
if (difference > 3600) {
clearInterval(x);
}
}, 1000
);
</script>
问题陈述:
我想知道我应该对上面的 js(或 php)代码进行哪些更改,以便在 60 分钟内没有 activity 时,它应该更新列 open 到 false(在 table trace_users 中)。
编辑 1:
我的登录代码和会话历史代码在同一个文件中/mno.php。我已将所有内容放在同一个文件 /mno.php 中。
这是网页的简单时间验证:
$modified_on = isset($SERVER['HTTP_IF_MODIFIED_SINCE']) ? $SERVER['HTTP_IF_MODIFIED_SINCE'] : null;
$current_time = time();
if (!is_null($modified_on) && ($current_time - strtotime($modified_on)) > 3600) {
session_destroy();
...
}
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $current_time).' GMT');
...
我想你知道这段代码
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 3600)) {
//...
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
在每个请求上运行,仅在请求到达时运行
想象一下,我访问了您的网站,然后在浏览器打开的情况下出去购物。你认为会发生什么? NOTHING - 因为不会有新的请求发送给你(假设你没有实施任何定期 ajax 轮询/Websocket 机制)
所以服务器不会理我,直到我购物回来刷新页面,服务器才会意识到"Hmmm..This guy's LAST_ACTIVITY is older than an hour let me update my trace_users
table and set open as false
for him"
来到你提出的解决方案,它看起来不错并且避免了 websockets/periodic ajax 请求的复杂性
只需要一些小的更正,请按照此处进行基本演示
<script>
var lastActivity = <?php echo ($_SESSION['LAST_ACTIVITY']); ?>; //the timestamp of latest page refresh or navigation
//This will remain constant as long as page stays put
var now = <?php echo time() ?>; //This takes inital value (technically same as LAST_ACTIVITY) from server
// but later on it will be incremented by javascript to act as counter
var logoutAfter = 5; //I set 5 sec for demo purposes
var timer = setInterval(function() {
now++;
let delta = now - lastActivity;
if ( delta > logoutAfter) {
alert('you are logged out');
clearInterval(timer);
//DO AJAX REQUEST TO close.php
}
}, 1000);
</script>
这里的 lastActivity
将保存页面由服务器发送到浏览器时的时间戳,它永远不会被浏览器上的脚本更改,
now
是您的计数器,您将使用它来跟踪自页面加载到浏览器以来经过了多少时间,您将每秒递增它并检查是否已超过给定的时间量
如果 true 执行 ajax 请求(或简单地重定向到 logout.php),您将在其中销毁会话并更新 trace_users
table 以将用户标记为已关闭
更新
所以ajax会像
$.ajax({
url: "/close.php",
type: 'POST', // GET also fine
data: { },
success: function(data) {
window.location.href= '/mmo.php';
},
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus);
}
});
和
close.php
<?php
session_start();
$logoutAfter = 5; //5 sec timeout for testing purposes
// I'm not sure whether the below if condition check is required here or not
// because we have already checked (whether to timeout or not ) in our javascript
// and we call close.php only when it's affirmative
// I encourage you to test and find out :)
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > $logoutAfter)) {
session_destroy(); // destroy session data in storage
!isset($_SESSION['pageadmin']);
/* Update Table (START) */
$open="false";
$stmt= $connect->prepare("UPDATE trace_users SET open=? WHERE user_name=?");
$stmt->bind_param('ss', $open, $_SESSION['user_name']);
$stmt->execute();
/* Update Table (END) */
//header('location: /mmo.php'); //<-- no need of it when url hit by ajax
exit();
}
else //<-- note the else
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
我认为 Vineys 和 jo0gbe4bstjbs 的回答是错误的,因为当用户关闭浏览器直到 5 秒时,它无法在 60 分钟和会话后更新 table。会话在 php.ini 配置文件中设置的时间后立即删除。 你介意每 5 秒请求一次是解决这个问题的好方法吗?这对性能来说是最糟糕的。 如果你想专业地解决这个问题,你应该添加 "last_request" 列并从 table 中删除 "open" 列,并且在每个请求之后你应该将 last_requests 值更新为当前的 unix 时间戳.在获取用户的地方你应该写:
$time = time() - 3600;
"SELECT * FROM `users` WHERE last_request > $time" //active users
"SELECT * FROM `users` WHERE last_request <= $time" //inactive users
而不是 ajax 每 5 秒请求一次,你应该写 setTimeout 3600 秒延迟时间 运行 window.location.href= '/mmo.php';代码。 如果您想要最佳性能并在 60 分钟注销后获得准确结果,这很好
Page.php
<!-- CODE TO INCLUDE IN HEADER.PHP -->
<?php
session_start();
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
?>
<!-- CLOSE -->
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
</head>
<body>
</body>
<script>
let lastActivity = <?php echo ($_SESSION['LAST_ACTIVITY']); ?>; //the timestamp of latest page refresh or navigation
//This will remain constant as long as page stays put
let now = <?php echo time() ?>; //This takes inital value (technically same as LAST_ACTIVITY) from server+
// but later on it will be incremented by javascript to act as counter
let logoutAfter = 5; //I set 5 secs for demo purposes
let timer = setInterval(function() {
now++;
let delta = now - lastActivity;
if ( delta > logoutAfter) {
alert('you are logged out');
clearInterval(timer);
//DO AJAX REQUEST TO close.php
$.ajax({
url: "/mmo.php",
type: 'POST', // GET also fine
data: { },
success: function(data) {
},
error: function(jqXHR, textStatus, errorThrown) {
console.log("I am inside error");
alert(textStatus);
}
});
}
}, 1000); //<-- you can increse it( till <= logoutAfter ) for better performance as suggested by @"Space Coding"
</script>
</html>
mmo.php
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
$connect = new mysqli($servername, $username, $password, $dbname);
if ($connect->connect_error) {
die("Connection failed: " . $connect->connect_error);
}
session_start();
$logoutAfter = 5; //5 sec timeout for testing purposes
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > $logoutAfter)) {
session_destroy(); // destroy session data in storage
!isset($_SESSION['pageadmin']);
/* Update Table (START) */
$open="false";
$stmt= $connect->prepare("UPDATE trace_users SET open=? WHERE user_name=?");
$usname = !empty($_SESSION['user_name'])?$_SESSION['user_name']:'';
$stmt->bind_param('ss', $open, $usname );
$stmt->execute();
/* Update Table (END) */
//header('location: /mmo.php'); //<-- no need of it when url hit by ajax
exit();
}
else //<-- note the else
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
?>