Таймер сеанса PHP работает изначально, но ушел неправильно

Так что у меня есть таймер php-сессии, который работает, но каким-то образом выходит из строя через некоторое время … это код и журнал консоли, который я получил. Я ищу решение этой проблемы или, возможно, другой набор кода для достижения того же эффекта таймера (поскольку я не уверен, что использование сессии — лучший метод для таймера)

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 минут и сумел эхо «$ время прошло»; в то время как ошибка только произошла позже

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 будет загружать весь процессор, постоянно проверяя, не произошел ли таймер, поэтому вы должны поспать несколько секунд внутри.

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;

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

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