Show loop result in real time

7

I'm using a loop to send mail from an array. Each time the loop runs the sleep(4); function is executed.

The problem is that the output of php only happens at the end, ie the echo "</br>n:".$ne."&nbsp".$user["email"]."</br> >>enviado</br>"; lines are output all at once and after all loops executed.

I would like as each loop runs, the echo function is displayed (one by one and not one at a time at the end).

foreach($users as $user) {
  $message->setTo($user["email"], $user["nome"]);
echo "\n";sleep(4);
  flush(); 
  ob_end_flush();  
  echo date('h:i:s');
  $mailer->send($message);
echo date('h:i:s') . "\n";

  $ne++;
  echo "</br>n:".$ne."&nbsp".$user["email"]."</br> >>enviado</br>";
    
asked by anonymous 19.01.2016 / 17:14

2 answers

4

You're probably talking about ob_implicit_flush . Yes, it is possible to display an output in the same php while looping, without expecting that loop to be finished yet. That is, the data is printed in stack.

ob_implicit_flush(true);


foreach (range(1, 50) as $value)
{
    echo "Imprimindo {$value}";
    ob_flush();

    sleep(1);
}

My php.ini is configured to automatically start a buffer.

If you do not know if your output buffer is automatic or not in your php.ini, you can do this little check for everything to work correctly.

if (ob_get_level() > 0) { 
    ob_start();
}

Still complementing the answer, you can do this only by using the flush function, as long as you are not using anything related to the output buffer in your code.

So you can do it like this:

// Fallback para garantir que não vai ter a configuração no php.ini

while(ob_get_level() > 0) ob_end_clean();    

foreach (range(1, 50) as $value)
{
    echo "Imprimindo {$value}";
    flush();

    sleep(1);
}

I tested both ways and worked perfectly on my machine.

    
19.01.2016 / 17:32
1

There are several techniques that may or may not work according to the environment.

Here is a slightly different example of what has already been posted:

ini_set('zlib.output_compression', 0);
ini_set('implicit_flush', 1);
ob_end_clean();

echo 'Hello World!';
flush();
ob_flush();

for ($i = 1; $i < 6; $i++) {
    sleep(1);
    echo PHP_EOL.'<br />'.$i;
    flush();
    ob_flush();
}

The only difference is that in this example we disable zlib compression, which is usually turned on by default .

Also important that we are using ob_end_clean () before starting the processes to ensure that any existing output buffer is deleted.

It does not necessarily have to be placed in the first line of codes. Just be before the initial logic of the buffer script you want to work with.

One problem you may have in this example is that the last loop does not respect sleep(1) , because it prints soon after the penultimate. But this behavior does not happen in certain environments.

It's very complicated to hit something that works 100%. There is no magic that makes it work consistently in every kind of environment. You have to test and adapt it for your specific case.

    
19.01.2016 / 22:43