-1

我正在制作一个测试计时器,它允许用户根据总计时器或单个问题计时器进行测试。我需要这个计时器在完成后保存到数据库中,以查看它是否按时完成,或者在时间用完时停止测试。问题是如果用户以任何方式退出,我需要恢复它。函数“register_shutdown_function()”和“pcntl_signal()”捕获正常的退出事件,但我想知道是否有任何东西可以捕获所有退出事件,甚至手动杀死浏览器(使用任务管理器之类的东西)或蓝屏错误,或断电等。 Cookies 可以工作,但用户从各个站点切换。我发现的唯一选择是每 10 秒保存一次(因为每秒保存一次会消耗带宽和 PC 资源)。有什么建议吗?

4

1 回答 1

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>

当用户单击开始测验时,将在数据库中创建一个会话,记录他们第一次单击开始的时间。然后,当时间超过允许的最大时间时,会话被删除并停止测验。

我添加了轮询,因此如果用户随时关闭测验,服务器将跟踪他们停止的位置并允许他们继续。

于 2013-05-05T04:16:56.500 回答