Search code examples
phpob-start

How to properly flush PHP echo output


I am using PHPMailer to send emails with attachments.

Each email takes about 5 seconds to send, and the PHP can send up to 5 emails with a total in that case of 10 PDFs...

During all that time, the browser shows a white page.

<?php
echo '<div>some spinner html</div>';
// code here to send emails
if (!$mail->send()) {
    echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
    echo 'Message sent!';
}

echo 'all the rest of the html';
?>

This doesn't work... I have the feeling I can use an ob_start() to buffer the rest of the page and only show a spinner.


Solution

  • Real answer: Use JS and create an API using PHP

    Best solution to your problem is using JavaScript and XHR and make a beautiful UI for it. If you want to show a loading and remove it after emails sent and show other stuff after disappearance of loading, it's only possible through JS. PHP is just a server side language capable of sending a response to browser and have no access to rendered page!

    Flush output

    Just use ob_flush() and flush() functions:

    echo '<div>some spinner html</div>';
    ob_flush();
    flush();
    // code here to send emails
    if (!$mail->send()) {
        echo 'Mailer Error: ' . $mail->ErrorInfo;
        ob_flush();
        flush();
    } else {
        echo 'Message sent!';
        ob_flush();
        flush();
    }
    
    echo 'all the rest of the html';
    

    Using implicit flush

    This looks like the previous one, but reduced a function call. this removes the flush() call!

    ob_implicit_flush(true)
    echo '<div>some spinner html</div>';
    ob_flush();
    // code here to send emails
    if (!$mail->send()) {
        echo 'Mailer Error: ' . $mail->ErrorInfo;
        ob_flush();
    } else {
        echo 'Message sent!';
        ob_flush();
    }
    
    echo 'all the rest of the html';
    

    Turn off output buffer

    Other solution is to turn off output buffer:

    while (@ob_end_flush());
    echo '<div>some spinner html</div>';
    // code here to send emails
    if (!$mail->send()) {
        echo 'Mailer Error: ' . $mail->ErrorInfo;
    } else {
        echo 'Message sent!';
    }
    
    echo 'all the rest of the html';