PHP会话计时器最初可以工作,但是走错了

时间:2018-12-25 02:27:32

标签: php session timer countdowntimer

所以我有一个可以工作的php会话计时器,但过了一段时间后就以某种方式出错了……这是我得到的代码和控制台日志。我正在寻找解决此问题的方法,或者可能是寻求一套不同的代码来实现相同的计时器效果(因为我不确定使用会话是否是计时器的最佳方法) < / p>

session_start();
function timer($time) {
        //Set the countdown to 120 seconds.
    $_SESSION['countdown'] = $time*60;
        //Store the timestamp of when the countdown began.
    $_SESSION['time_started'] = time();

    $now = time();
    $timeSince = $now - $_SESSION['time_started'];
    $remainingSeconds = abs($_SESSION['countdown'] - $timeSince);
    $counter = 0; 

    $minutes = $remainingSeconds/60;
    echo "$minutes minutes countdown starts.".PHP_EOL;
    while($remainingSeconds >= 1) {
        $now = time();
        $timeSince = $now - $_SESSION['time_started'];

        if (($timeSince-$counter) >= 60) {
            $remainingSeconds = abs($_SESSION['countdown'] - $timeSince);
            $counter = $timeSince;
            $minutes = $remainingSeconds/60;
            echo "$minutes minutes has passed.".PHP_EOL;
        }
    }

    if($remainingSeconds < 1){
        session_abort(); 
        return true;
    }
}

if($this->timer(30)) {
        // do whatever
        echo "$time has passed";
    }

这是控制台中发生的事情:

30 minutes countdown starts.
29 minutes has passed.
.... (continue as per pattern)
16 minutes has passed.
15 minutes has passed. (problem occurs here)
8.7166666666667 minutes has passed.
7.7166666666667 minutes has passed.
6.7166666666667 minutes has passed.
.... (continue as per pattern)
0.71666666666667 minutes has passed.
0.28333333333333 minutes has passed.
1.2833333333333 minutes has passed.
2.2833333333333 minutes has passed.
.... (continue as per pattern all the way)

附加说明:会话计时器并非总是重现此相同的模式,有时它会运行30分钟并设法回显“ $时间已过”; 只会在以后发生

2 个答案:

答案 0 :(得分:0)

我还没有运行您的软件,但是仅阅读它,我认为其中有一些非常错误的地方。

  1. 会话。您没有正确使用它们。

会话值仅应设置一次,这意味着在进行$_SESSION['countdown'] = $time*60;$_SESSION['time_started'] = time();之前,应检查它们是否已存在,并且仅在不存在时进行分配。您当前的代码每次刷新页面时都会重置时钟,这违背了会话的目的。

  1. abs。我认为您也没有正确使用它们。

您不应一直吸收剩余的秒数。 $remainingSeconds = abs($_SESSION['countdown'] - $timeSince);应该被设为负数。剩下的秒数为负数表示您的超时已过期/您错过了!调用abs意味着,如果您有任何机会错过确切的活动时间,则可以让它永久消失。 这是您主要问题的答案。解决此问题,您的计数器将停止为零并再次备份。

  1. 您依靠代码正确地检查每一秒钟。但事实并非如此。

由于某些原因导致代码延迟并且无法正确检查60秒时,就会出现令人讨厌的小数,这意味着除以60的结果不是完美的四舍五入,而您得到8.7166666分钟。

如果您从删除abs调用开始,并且通常尝试稍微简化一下代码,我相信您很快就会使它按预期工作。

//编辑1

这是一种非常幼稚但简化的解决方法。我在那儿留下了两个不同的输出,供您选择一个。

function timer($time) {
    echo "$time minutes countdown starts." . PHP_EOL;

    // Save the date in future when the timer should stop
    $endTime = time() + $time * 60;

    // Keeps track of last full minute to simplify logs
    $lastFullMinute = $time;

    while(true) {
        $timeRemaining = $endTime - time();

        if ($timeRemaining <= 0) {
            // Time remaining is less than zero, which means we've gone beyond the end date.
            // End the loop
            return;
        }

        // Round up!
        $minutesRemaining = ceil($timeRemaining / 60);
        if ($minutesRemaining != $lastFullMinute) {
            // Current "minute" is different than the previous one, so display a nice message

            // If you want to show how many minutes are remainig, use this:
            echo "$minutesRemaining minutes remaining." . PHP_EOL;

            // If you want to show how many minutes have passed, you have to take mintutesRemaining away from the original time
            $minutesPassed = $time - $minutesRemaining;
            echo "$minutesPassed minutes passed." . PHP_EOL;

            $lastFullMinute = $minutesRemaining;
        }
    }
}

进一步改进它的主要方法是使用sleep函数http://php.net/manual/en/function.sleep.php。当前while loop会通过不断检查计时器是否发生来占用所有CPU,因此您应该在内部睡眠几秒钟。

答案 1 :(得分:0)

您如何看待该解决方案?从上面引用

function timer($time) {
echo "$time minutes countdown starts." . PHP_EOL;

// Save the date in future when the timer should stop
$endTime = time() + $time*60;

while(true) {
    sleep(20);
    $secondsRemaining = $endTime - time();

    if ($secondsRemaining <= 0) {
        echo 'Finished';
        return true;
        }
    }
}