2010-08-10 3 views
5

Я пытаюсь запустить цикл каждую секунду в течение 25 секунд в основном.php output with sleep()

for($i = 0; $i <= 25; $i += 1){ 
    echo $i; 
    sleep(1) 
} 

Дело в том, что оно не выводится до тех пор, пока оно не будет полностью выполнено, поэтому после того, как цикл продолжится 25 раз. Есть ли способ сделать это, чтобы он выдавался перед каждым сном? и не дожидаться завершения полного цикла?

Спасибо!

+0

Ваш браузер и контент? Некоторые браузеры не будут отображать HTML до тех пор, пока не столкнутся с закрывающим тегом. Обычный текст может быть лучшим вариантом, если вы хотите «живое обновление» контента. – mwalker

+1

Это похоже на проблему, с которой лучше справиться на стороне клиента. Вы можете получать с сервера с помощью AJAX каждую секунду. –

+2

это абсолютно то, что НЕ должно быть сделано так, как вы пытаетесь на сервере .. используйте некоторые ajax и setTimeout или такие в браузере вместо этого. –

ответ

4

Вызов flush заставит PHP вытолкнуть весь выходной буфер на клиент, прежде чем продолжить.

for($i = 0; $i <= 25; $i += 1){ 
    echo $i; 
    flush(); 
    sleep(1); 
} 

EDIT:

После тестирования это на моем сервере LightTPD я заметил, что он буферный мои выходы в блоках 4096 символов, и я предполагаю, что другой браузер может иметь аналогичные схемы буферизации. Также GZIP может полностью предотвратить flush. К сожалению, нет способа проверить, что он работает из-за характера HTTP.

Еще одна проблема с этой стратегией заключается в том, что она оставляет блокировку PHP proc для других запросов. Это может привести к сбоям запросов.

+0

Хмм .. Не похоже на трюк. Также попробовал w/ob_start(), ob_flush() и flush() – dzm

+1

Обычно комбо 'ob_end_flush() '(пропустите' ob_start() ') и' flush() 'делает это. У вас есть прокси-сервер между вами и сервером с PHP? –

+0

Работал для меня через командную строку, но не в браузере ... после того, как я положил точку с запятой после сна (1) –

8

То, что вы пытаетесь достичь, - это инкрементный вывод в браузер из PHP.

Возможно ли это, зависит от вашего сервера и от того, как вы вызываете PHP.

PHP под FastCGI

Вы, вероятно, немного больше шансов столкнуться с такой проблемой, когда PHP работает под FastCGI, а не как модуль Apache, так как взаимодействие между сервером и процессы PHP не так тесно связаны. Коммуникация FastCGI использует буферизацию вывода после того, как данные оставили процессы PHP, причем вывод отправлен в браузер только после полного завершения запроса или заполнения этого буфера. Вдобавок к этому, процессы PHP, как правило, прекращаются через определенное количество времени, чтобы не позволить кому-либо работать слишком долго.

При этом комбинация ob_end_flush() (или ob_flush()) и flush() должна по-прежнему приводить к тому, что PHP запрашивает сброс нисходящих буферов, поэтому это может по-прежнему работать. Возможно, вам также потребуется выяснить, нужно ли вам ограничивать время для скриптов PHP.

PHP под mod_php

Если вы используете mod_php, вы можете написать пошагово к браузеру. Используйте команду flush(), чтобы убедиться, что модуль PHP мгновенно очистит ее. Если у вас нет буферизации вывода или какого-либо модуля Apache, такого как mod_gzip, он должен немедленно выйти в браузер пользователя. Более того, вы можете поддерживать свой PHP-скрипт до тех пор, как вам нравится (с помощью set_time_limit() в PHP), в соответствии с конфигурациями по умолчанию, хотя, конечно, он будет потреблять некоторую память.

У вас могут возникнуть проблемы с некоторыми браузерами, которые не начинают рендеринг страницы до тех пор, пока не будет загружена определенная часть страницы. Некоторые версии IE могут ждать 1 КБ. Я обнаружил, что Chrome может ждать больше. Множество людей обойти это, добавив дополнение, например длинный комментарий 1 или 2 КБ в верхней части документа.

3

Я просто проделал эту же проблему с точки зрения новичка и придумал этот скрипт с голой костью, который будет делать то, что вы хотите.

<?PHP 
ob_start(); 
$buffer = str_repeat(" ", 4096)."\r\n<span></span>\r\n"; 

for ($i=0; $i<25; $i++) { 
    echo $buffer.$i; 
    ob_flush(); 
    flush(); 
    sleep(1); 
} 

ob_end_flush(); 
?> 

Вопросы, которые вы можете спросить может быть here (около \r\n) и here (около ob_flush()). Надеюсь, что это поможет тебе.