2013-05-05 59 views
-1

我正在製作一個測試計時器,它允許用戶根據總計時器或單個問題計時器進行測試。我需要這個定時器在完成時保存到數據庫,以確定它是否按時完成,或者如果時間用完就停止測試。問題是我需要這個恢復,如果用戶以任何方式退出。函數「register_shutdown_function()」和「pcntl_signal()」會捕獲正常的退出事件,但是我想知道是否有任何事情可以捕獲所有退出事件,甚至手動殺死瀏覽器(像任務管理器一樣)或藍屏錯誤,或斷電等。Cookie可以工作,但用戶從各個站點切換。我發現的唯一選擇是每10秒鐘節省一次(因爲每秒節省會消耗帶寬和PC資源)。有什麼建議?退出PHP保存計時器

+0

你有沒有嘗試過使用數據庫的任何東西? – 2013-05-05 03:50:18

+0

數據庫設置完成,如果相應使用,則會正確保存。如果以強制或突然退出應用程序(如我剛​​才提到的示例),問題不在於丟失計時器 – 2013-05-05 04:03:27

回答

0

在這個例子中,我將做一個SQL表的格式:

id,session,expire 
----------------- 
1,d41d8cd98f00b204e9800998ecf8427e,1367727317 

要建立這個表格的使用:

CREATE TABLE `quizzes` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `session` varchar(32), 
    `expire` int(11), 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `uc_session` (`session`) 
); 

現在最有趣的部分。後端:

<?php 
$expire_time=20; //twenty seconds 
$precision=2; //how accurate the time is (lower = better, but more polls) 

$db_host="127.0.0.1"; 
$db_user="root"; 
$db_pass="DATABASE_PASSWORD"; 
$db_db="DATABASE_NAME"; 

$precision_mill=$precision*1000; 
$script=<<<ZZZ 

<script> 
    function keepAlive() { 
     var xmlhttp; 
     if (window.XMLHttpRequest) { 
      xmlhttp=new XMLHttpRequest(); 
     } else { 
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); 
     } 
     xmlhttp.onreadystatechange=function() { 
      if (xmlhttp.readyState==4 && xmlhttp.status==200) { 
       if (xmlhttp.responseText=="expired") { 
        clearInterval(interval); 
        clearInterval(minusTime); 
        document.getElementById("timeleft").innerHTML = 0; 
        alert("Quiz Expired. Please start a new one."); 
        return; 
       } 
       document.getElementById("timeleft").innerHTML = xmlhttp.responseText; 
      } 
     } 
     xmlhttp.open("GET",document.URL+"?keepalive",true); 
     xmlhttp.send(); 
    } 
    function keepTime() { 
     document.getElementById("timeleft").innerHTML-=1; 
    } 
    var interval=setInterval(keepAlive,$precision_mill); 
    var minusTime=setInterval(keepTime,1000); 
</script> 

ZZZ; 

if (isset($_COOKIE['session'])) { 
    $mysqli=new Mysqli($db_host,$db_user,$db_pass,$db_db); 
    $session=$mysqli->real_escape_string($_COOKIE['session']); 
    $expire=$mysqli->query("SELECT `expire` FROM `quizzes` WHERE `session`='".$session."'"); 
    $expire=$expire->fetch_assoc(); 
    if (isset($expire['expire'])) { 
     $expire=$expire['expire']; 
     if (isset($_GET['keepalive'])) { 
      $expire-=$precision; 
      if ($expire<=0) { 
       $mysqli->query("DELETE FROM `quizzes` WHERE `session`='".$session."'"); 
       setcookie("session","",time()-3600); 
       echo "expired"; 
       $mysqli->close(); 
       exit; 
      } 
      $mysqli->query("UPDATE `quizzes` SET `expire`=".$expire." WHERE `session`='".$session."'"); 
      echo $expire; 
      exit; 
     } 
     ?> 
    <!DOCTYPE html> 
<html> 
    <head> 
     <?php 
      echo $script; 
     ?> 
    </head> 
    <body> 
     <?php 
      echo 'Quiz resumed, you currently have <div style="display:inline" id="timeleft">'.$expire.'</div> second(s) left.'; 
     ?> 
    </body> 
</html> 
     <?php 
     $mysqli->close(); 
     exit; 




    } else { 
     echo "Quiz expired. Please start a new one."; 
     exit; 
    } 
} else { 
    if ($_SERVER['REQUEST_METHOD']==='POST') { 
     $mysqli=new Mysqli($db_host,$db_user,$db_pass,$db_db); 
     $session=str_shuffle(md5(microtime())); 
     $mysqli->query("INSERT INTO `quizzes`(`session`,`expire`) VALUES('".$session."',".$expire_time.")"); 
     setcookie("session",$session); 
     ?> 
<!DOCTYPE html> 
<html> 
    <head> 
     <?php 
      echo $script; 
     ?> 
    </head> 
    <body> 
     <?php 
      echo 'Quiz started, you currently have <div style="display:inline" id="timeleft">'.$expire_time.'</div> second(s) left.'; 
     ?> 
    </body> 
</html> 
     <?php 
     $mysqli->close(); 
     exit; 
    } 
} 
if (isset($_GET['keepalive'])) { 
    echo "expired"; 
    exit; 
} 
?> 
<!DOCTYPE html> 
<html> 
    <head> 
     <title>Quiz</title> 
    </head> 
    <body> 
     <form method="post" action=""> 
      <input type="Submit" value="Start Quiz"> 
     </form> 
    </body> 
</html> 

當用戶點擊開始測驗時,會在數據庫中創建一個會話,以跟蹤他們第一次點擊開始的時間。然後,當時間過去後,允許最大時間,會話被刪除,測驗停止。

我添加了輪詢,所以如果用戶在任何時候關閉測驗,服務器將跟蹤他們停止的位置並允許它們恢復。

+0

感謝您的回覆。假設一個特定的場景,假設(在你的第二個例子中)用戶在11秒鐘,並且有一個權力,如果第二天他用另一臺PC登錄,他將如何在12又是幾秒?您的會話允許信息保存開始時間,但是如果他啓動,中斷並稍後再開始? – 2013-05-05 21:45:41

+0

您將需要使用ajax。但是,這不容易被利用嗎?如果用戶可以「假裝」停電,他們可以將測驗延長到任何他們需要的時間。 – 2013-05-05 22:57:49

+0

我知道它很容易被利用,但這是用戶想要的。雖然每頁只有1個問題,但這樣有幫助。感謝ajax提示,我想沒有辦法在純PHP上做到這一點。 – 2013-05-06 01:53:15