I'm trying to post some data to post.php
and I want the result to display in form.html
, I used Ajax to get php output without needing to reload the page, what I couldn't figure out is how to flush some of the php output before the php script finishes.
I tried flush()
and ob_flush()
but it seems that they don't work when used with Ajax. My goal is to update form.html
in real time without reloading the page.
Here is an example of what I'm trying to achieve. Source Code:
form.html
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery.validate/1.7/jquery.validate.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#myform").validate({
submitHandler: function(form) {
// do other stuff for a valid form
$.post('post.php', $("#myform").serialize(), function(data) {
$('#results').html(data);
});
}
});
});
</script>
</head>
<body>
<form name="myform" id="myform" action="" method="POST">
<!-- The Name form field -->
Name:
<input type="text" name="name" id="name" size="30" value=""/>
<br>
<!-- The Email form field -->
Email:
<input type="text" name="email" id="email" size="30" value=""/>
<br>
<!-- The Submit button -->
<input type="submit" value="Submit"/></div>
</form>
<!-- Result goes here -->
<div id="results"><div>
</body>
</html>
post.php
<?php
for($i=0;$i<2;$i++) {
echo "Your Name is ".$_POST['name']. "<br/>";
echo "Your E-mail is".$_POST['email']."<br/>";
echo "Waiting 2s <br/><br/>";
//I want to print the above before waiting 2 seconds.
sleep(2);// in real application this will be equivalent of some calculation that takes time.
}
?>
Your echos may already be sent to the client browser, but the client will be kept waiting for further output until your PHP script actually finishes. You need to disconnect the client early, eg: before sleep(2)
. Try this:
ignore_user_abort(true);
// Disconnect with the client
if (!connection_aborted()) {
$response = 'your response';
header('Content-Length: ' . strlen($response));
header('Connection: close');
echo $response;
flush();
}
Note that please do not do other echos before above code block. All your output should be in $response
, since Content-Length
must be calculated correctly.
You can't simply return a single page request in form of several sequential outputs because each page load (may it be a normal HTTP request from a browser or a script-wise AJAX request) is a result of a client asking for a page and a server delivering the matching document. It's not simply PHP generating and delivering output, it's the webserver fulfilling a page request independant of the nature of the given requested resource and it won't serve a half-completed page.
This may be an alternative to your initial idea: example of AJAX-style multi-step operation:
Backend: post.php:
<?php
echo "Your Name is ".$_POST['name']. "<br/>".
"Your E-mail is".$_POST['email']."<br/>".
"Will now continue with calculation job ...";
// store the values inside db, create session and return content
...
post-calculation.php
<?php
// longer running script doing stuff
...
print 'Done.';
Frontend:
Modify your script as follows:
<script type="text/javascript">
$(document).ready(function(){
$("#myform").validate({
submitHandler: function(form) {
// do other stuff for a valid form
$.post('post.php', $("#myform").serialize(), function(data) {
// will return the content from post.php
$('#results').html(data);
// now call the second process
$.ajax('post-calculation.php', {
success: function(result) {
$('#results').append(result);
}
});
});
}
});
});
</script>
Remarks:
This should be seen as just an example and not as good practice of how to perform AJAX calls with a multiple step operation. It is advisable to use output formats that allow a script to react on errors that may occur while calling a backend script i.e. through not returning HTML code but JSON instead [1]. You may want to store some part of earlier received data inside a $_SESSION variable to re-use the data afterwards in a later running script, don't forget to always call session_start();
before you access the session object.
[1] http://www.sitepoint.com/ajaxjquery-getjson-simple/ (simple tutorial)