Continuer l'exécution d'un script PHP sur le serveur en libérant le navigateur web client (après que la page ait été envoyée)

Post PHP server-side execution : Continuer l'exécution d'un script PHP après que la page a été envoyé

Imaginez ce scénario. Vous avez une page Web accédée par un utilisateur web. Une fois envoyée à travers le réseau et à destination de son navigateur, vous voulez exécuter du code PHP coûteux.

The issue is that the users browser will continue to say the page is loading because the connection remains open. This code solves this issue. It works by ending the previous HTTP content being sent at the start of your PHP script and then sends a new header which it ends itself later.

Le problème est que le navigateur des utilisateurs continuera à-dire que chargement de la page n'est pas terminé car la connexion reste ouverte. Ce code permet de résoudre ce problème. Il agit en terminant le contenu HTTP précédent envoyés au début de votre script PHP et envoie ensuite un nouvel en-tête qui se termine plus tard.

<?php
    /**
     * Helper functions for manually starting and then ending the
     * connection. By using this you can end the session later whilst
     * the script is still running and so allow server side processing
     * to continue.
     * 
     * On the downside this ignores user aborting of loading the page.
     * 
     * Note that startNewHTTPHeader must be called before headers are sent.
     */
 
    /**
     * This must be called before headers are sent!
     * 
     * This ends the default header and starts a new one.
     * This new one can be ended at any time using endHTTPHeader.
     */
    function startNewHTTPHeader()
    {
        ob_end_clean();
        header("Connection: close\r\n");
        header("Content-Encoding: none\r\n");
        ignore_user_abort( true ); // optional
        ob_start();
    }
 
    /**
     * Note that this must be called after startNewHTTPHeader!
     * 
     * Ends the header (and so the connection) setup with the user.
	 * All HTTP and echo'd text will not be sent after calling this.
	 * This allows you to continue performing processing on server side.
     */
    function endHTTPHeader()
    {
        // now end connection
        header( "Content-Length: " . ob_get_length() );
        ob_end_flush();
        flush();
        ob_end_clean();
    }
?>

Exemple d'utilisation : Importer les fonctions, appeler startHTTPConnection() au début de votre script PHP et endHTTPConnection() à la fin de l'envoi de votre HTML (avant votre ultime et long script côté serveur).

<?php
    // import the library
    include 'httpHeader.php';
	startNewHTTPHeader();
?>
<html>
	<head></head>
	<body>
		My Website
	</body>
</html>
<?php
	endHTTPHeader();
 
	// post script code goes here!
?>

Ressources

  • ignore_user_abort Active l'interruption de script sur déconnexion du visiteur
  • ob_start Enclenche la temporisation de sortie
  • ob_end_clean Détruit les données du tampon de sortie et éteint la temporisation de sortie
  • ob_end_flush Envoie les données du tampon de sortie et éteint la temporisation de sortie
  • ob_end_clean Détruit les données du tampon de sortie et éteint la temporisation de sortie
  • flush Vide les tampons de sortie
function endOutput($endMessage){
    ignore_user_abort(true);
    set_time_limit(0);
    header("Connection: close");
    header("Content-Length: ".strlen($endMessage));
    echo $endMessage;
    echo str_repeat("\r\n", 10); // just to be sure
    flush();
}
 
// Must be called before any output
endOutput("thank you for visiting, have a nice day");
 
sleep(100);
mail("you@yourmail.com", "ping", "i'm here");