2010-08-10 20 views
5

Estoy tratando de ejecutar un bucle cada segundo durante 25 segundos, básicamente.salida php con sleep()

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

Lo que pasa es que no sale hasta que está completo, por lo tanto, después de que el ciclo continúa 25 veces. ¿Hay alguna manera de hacer esto para que salga antes de cada sueño? y no esperar hasta que se complete el ciclo completo?

Gracias!

+0

¿Cuál es su navegador y contenido? Algunos navegadores no mostrarán HTML hasta que encuentren una etiqueta de cierre. El texto sin formato puede ser una mejor opción si desea contenido de "actualización en vivo". – mwalker

+1

Esto parece ser un problema mejor abordado en el lado del cliente. Puede recuperar desde el servidor usando AJAX cada segundo. –

+2

esto es absolutamente algo que NO se debe hacer de la manera en que se está probando en el servidor ... utilice un ajax y un setTimeout o similar en el navegador en su lugar .. –

Respuesta

4

Llamar flush obligará a PHP a enviar todo el búfer de salida al cliente antes de continuar.

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

EDIT:

Después de probar esto en mi servidor lighttpd me di cuenta de que mis salidas amortiguada en bloques de 4096 caracteres, y supongo otro navegador podría tener esquemas de tampón similares. Además, GZIP puede evitar flush por completo. Lamentablemente, no hay forma de probar que funciona debido a la naturaleza de HTTP.

También otro problema con esta estrategia es que deja el proceso de PHP bloqueado para otras solicitudes. Esto puede causar que las solicitudes se acumulen.

+0

Hmm ... No parecía hacer el truco .. también probé w/ob_start(), ob_flush() y flush() – dzm

+1

Por lo general, el combo de 'ob_end_flush() '(omita el' ob_start() ') y' flush() 'lo hace. ¿Tiene un servidor proxy entre usted y el servidor que ejecuta PHP? –

+0

Funcionó para mí corriendo a través de la línea de comandos, pero no del navegador ... después de poner un punto y coma después de la suspensión (1) –

8

Lo que está tratando de lograr es una salida incremental para el navegador desde PHP.

Si esto se puede lograr puede depender de su servidor y de cómo está invocando PHP.

PHP bajo FastCGI

Usted es probablemente un poco más probabilidades de encontrarse con este tipo de problema cuando PHP se ejecuta en FastCGI más que como un módulo de Apache, debido a que el acoplamiento entre el servidor y los procesos de PHP no están tan estrechamente relacionados. La comunicación FastCGI utiliza el almacenamiento en búfer de salida una vez que los datos han salido de los procesos de PHP, con la salida enviada al navegador solo una vez que la solicitud está completa o este búfer se ha llenado. Además de esto, los procesos de PHP tienden a terminarse después de una cierta cantidad de tiempo, para evitar que cualquiera se ejecute por mucho tiempo.

Dicho esto, una combinación de ob_end_flush() (o ob_flush()) y flush() debería hacer que PHP solicite que se borren los búferes de flujo descendente, por lo que esto aún puede funcionar. Es posible que también deba investigar si necesita extender el límite de tiempo para los scripts PHP.

PHP bajo mod_php

Si está utilizando mod_php, se puede escribir de forma incremental a cabo en el navegador. Use el comando flush() para asegurarse de que el módulo PHP lo descargue instantáneamente. Si no tiene un búfer de salida, o algún módulo de Apache como mod_gzip, entonces debería salir al instante al navegador del usuario. Además, puede mantener su script PHP ejecutándose todo el tiempo que desee (con set_time_limit() en PHP), bajo las configuraciones predeterminadas, aunque, por supuesto, consumirá algo de memoria.

Puede tener problemas con algunos navegadores que no comienzan a mostrar la página hasta que se descarga cierta cantidad de página. Algunas versiones de IE pueden esperar 1KB. Descubrí que Chrome puede esperar más. Mucha gente soluciona esto agregando relleno, como un comentario largo de 1 o 2 KB de longitud en la parte superior del documento.

3

Acabo de resolver este problema desde la perspectiva de un principiante y presenté este sencillo script que hará lo que usted desee.

<?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(); 
?> 

Las preguntas que usted puede pedir que podría ser here (alrededor \r\n) y here (alrededor de ob_flush()). Espero que te ayude.