亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 php 會話超時時更新數據庫表

在 php 會話超時時更新數據庫表

PHP
慕哥9229398 2022-12-30 17:13:54
我有一個如下所示的 php 代碼,其中會話超時在沒有活動的 60 分鐘后發生。以下代碼位于文件/mno.php中。我的登錄和注銷代碼也在同一個文件/mno.php中。/mno.phpif (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 代碼中的表trace_users跟蹤所有登錄的用戶。在該表中,有兩列user_name和open。當任何用戶登錄/注銷時,該值設置為true/false。我已經包含了 sql 查詢,其中我試圖在沒有活動時更新表,但不幸的是,當 60 分鐘沒有活動發生時,該特定用戶的列值未設置為 false 。這是我試過的:在做了一些研究之后,我想我必須運行一個計時器(js/ajax)。在下面顯示的 javascript 中,我計算了Last Activity和Current time之間的差異。如果超過 60 分鐘,那么它將更新數據庫表。這是我嘗試過的,但我相信需要做更多的工作才能更新數據庫中的表。<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 分鐘內沒有任何活動時,它應該將該特定用戶的open列更新為false(在表trace_users中)。編輯 1:我的登錄代碼和會話歷史代碼在同一個文件/mno.php中。我已將所有內容放在同一個文件/mno.php中。
查看完整描述

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 分鐘注銷后獲得準確結果,它的方式很好


查看完整回答
反對 回復 2022-12-30
?
森林海

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 


查看完整回答
反對 回復 2022-12-30
?
海綿寶寶撒

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  

?>


查看完整回答
反對 回復 2022-12-30
?
慕蓋茨4494581

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');


...


查看完整回答
反對 回復 2022-12-30
  • 4 回答
  • 0 關注
  • 140 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號