4 回答

TA貢獻1852條經驗 獲得超1個贊
我認為 Vineys 和 jo0gbe4bstjbs 的回答是錯誤的,因為當用戶關閉瀏覽器直到 5 秒時,它也無法在 60 分鐘和會話后更新表格。會話在 php.ini 配置文件中設置的時間后立即刪除。你介意每 5 秒請求一次是解決這個問題的好方法嗎?這對性能來說是最糟糕的。如果你想專業地解決這個問題,你應該從表中添加“last_request”列并刪除“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
而不是每 5 秒發送一次 ajax 請求,你應該編寫 setTimeout,延遲時間為 3600 秒,運行 window.location.href= '/mmo.php'; 代碼。如果您想要最佳性能并在 60 分鐘注銷后獲得準確結果,它的方式很好

TA貢獻2011條經驗 獲得超2個贊
我想你意識到這段代碼
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 3600)) {
//...
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
在每個請求上運行,并且僅在請求到達時運行
想象一下,我訪問了您的網站,然后在保持瀏覽器打開的情況下出去購物。你認為會發生什么?NOTHING - 因為不會有新的請求發送給你(假設你沒有實現任何周期性的 ajax 輪詢/Websocket 機制)
所以服務器不會打擾我,直到我購物回來并刷新頁面,然后服務器才會意識到“嗯..這家伙的 LAST_ACTIVITY 已經超過一個小時讓我更新我的trace_users表并false為他設置打開”
來到您提出的解決方案,它看起來不錯并且避免了 websockets/周期性 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表以將用戶標記為已關閉
更新
所以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);
}
});
和
關閉.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

TA貢獻1809條經驗 獲得超8個贊
頁.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>
網游.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
?>

TA貢獻1850條經驗 獲得超11個贊
這是一個簡單的網頁時間驗證:
$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');
...
- 4 回答
- 0 關注
- 140 瀏覽
添加回答
舉報