Show real-time loop result

Asked

Viewed 1,573 times

7

I’m using a loop to send emails from an array. Every time the loop runs the function sleep(4); is executed.

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

I would like as each loop runs, the echo function is displayed (one by one and not at once 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>";
  • 1

    Very poorly crafted question, explain and detail better.

  • I think it’s clear now ...I edited the question...

  • This script runs in a browser or terminal?

  • in php browser

  • The PHP code is interpreted by the server, when the process ends the answer is returned to the browser, so it appears all at once. If this pause is necessary you will have to do this process via javascript/jQuery using AJAX requests.

  • Okay thanks I’ll investigate how to do that

  • @Edsonhoraciojunior wrong. If you want the result out in ranks you can too. I will answer the question.

  • I didn’t know the method quoted by @Wallacemaxters, good!

  • @Edsonhoraciojunior I also thought it was not possible to do this in PHP, but after I saw a javascript/php implementation with Stream updates and ob_implict_flush I changed my mind. http://www.html5rocks.com/en/tutorials/eventsource/basics/

  • 3

    And I don’t know if I’m wrong, but I think because of the ignorance of some that boy took negative votes.

  • 1

    The downvote people sneak out, as always :p

Show 6 more comments

2 answers

4


You’re probably talking about ob_implicit_flush. Yes, it is possible to display an output in php even while running a loop, without waiting for that loop to be finished. That is, the data is printed in a 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 don’t know whether your output buffer is automatic or not in your php.ini, you can do this little check to make sure everything works properly.

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

While complementing the answer, you can do this by just using the function flush, provided you are not using anything related to 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.

  • is...with me does not work must be from php.ini...

  • @I-amSam in another way. I combined with Bacco, I think he will show another way.

  • Huh? I just commented to start testing with only one flush() normal in the loop, to see if it solves. Then, only if it doesn’t work, test with the functions ob_flush() etc. I didn’t think to post reply, because that’s all I really commented on.

  • 'Cause I couldn’t figure it out anyway

  • So there’s your @Bacco. I edited it!

1

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

Here’s a slightly different example from the one already 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 the compression zlib, which is normally activated by default.

Important also that we are using ob_end_clean() before starting processes to ensure that any existing output buffer is deleted.

It does not necessarily need 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 above is that the last link does not respect the sleep(1), because it prints right after the penultimate. But this behavior does not happen in certain environments.

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

  • thanks, it didn’t work either but thanks :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.