Viewed   157 times

I want to run a relatively time consuming script based on some form input, but I'd rather not resort to cron, so I'm wondering if a php page requested through ajax will continue to execute until completion or if it will halt if the user leaves the page.

It doesn't actually output to the browser until a json_encode at the end of the file, so would everything before that still execute?

 Answers

5

It depends.

From http://us3.php.net/manual/en/features.connection-handling.php:

When a PHP script is running normally the NORMAL state, is active. If the remote client disconnects the ABORTED state flag is turned on. A remote client disconnect is usually caused by the user hitting his STOP button.

You can decide whether or not you want a client disconnect to cause your script to be aborted. Sometimes it is handy to always have your scripts run to completion even if there is no remote browser receiving the output. The default behaviour is however for your script to be aborted when the remote client disconnects. This behaviour can be set via the ignore_user_abort php.ini directive as well as through the corresponding php_value ignore_user_abort Apache httpd.conf directive or with the ignore_user_abort() function.

That would seem to say the answer to your question is "Yes, the script will terminate if the user leaves the page".

However realize that depending on the backend SAPI being used (eg, mod_php), php cannot detect that the client has aborted the connection until an attempt is made to send information to the client. If your long running script does not issue a flush() the script may keep on running even though the user has closed the connection.

Complicating things is even if you do issue periodic calls to flush(), having output buffering on will cause those calls to trap and won't send them down to the client until the script completes anyway!

Further complicating things is if you have installed Apache handlers that buffer the response (for example mod_gzip) then once again php will not detect that the connection is closed and the script will keep on trucking.

Phew.

Wednesday, September 21, 2022
4

If I understand what you want to happen then this is how I'm implementing it. It's in Prototype instead of jQuery but it shouldn't take you long to translate:

new Ajax.Request('process.php', {
    on401: function(response) {
        var redirect = response.getHeader('Location');
        document.location = redirect;
    }
});

In your PHP, output the following if the session is inactive:

header('Location: http://example.com/login.php', true, 401);
exit;
Monday, September 19, 2022
 
3

Short answer: YOU CAN'T

The session can be destroyed when the entire browser is closed by simply setting expire_on_close in config/session.php (also make sure you clear the cookies in your browser for this to work):

'expire_on_close' => true,

But there is no way to detect when only a tab is closed in the browser. The closest thing you would have is the JavasSript method onbeforeunload that triggers when you close a tab. But it also triggers when you navigate away from a page or hit the back button, and there's no way to differentiate between those actions.


You could set a very short session time on the server, and "ping" the server from any open page, to let it know to keep the session still in use, which would mean it would very quickly expire when the tabs that have the app open are closed, but that's an extremely ugly solution.

Wednesday, October 26, 2022
2

The PHP script should be killed as soon as the connection socket closes. If the script keeps on running when the user closes the page, there is something very wrong with your Apache/PHP configuration.

Socket closing can happen when the client calls EventSource.close() explicitely, the connection is lost due to network problems, the client closes the page or your PHP script terminates.

ignore_user_abort(false) does nothing; that's the default behaviour (the script terminates when the connection is closed). Passing true as a parameter would have your script survive the connection, but that would not solve your problem.

Your retry: 1000 serves no purpose since you're never closing the socket server-side. Your PHP script should be called when the client activates an EventSource object and terminate only at the client's request (or if the network fails), so whatever initial DB tweaking should occur only once per chat connection. That's assuming the client does not do anything that would close the connection.

Btw this will put a lot of strain to the server: you will have one PHP process per chatting client running for the whole chat duration, and the polling period is about 10 times too small (10 seconds is more than enough). Having the clients poll for new messages every 30 seconds or so would be less wasteful.

Monday, August 15, 2022
3

Thank you all for your inputs. I figured out a way to make it work.

I wanted to be able to send the data to the datatables within a jquery callback because this would allow me to create my own search outside the datatables. The way I've done it is by running an ajax call that performs the query to the database and then I pass the results of that query to the datatable but the issue was how to format the data in a way that the datatable would accept and how to make it read that data to display on the table.

Simple ajax call and populating the datatable

This code can be further modified (which I will do in my case) but it should give you an idea of how to accomplish what I've been wanting to do. (it works btw).

<script>
$('document').ready(function()
{
    $.ajax({
    type : 'POST',
    url  : 'test.php',
    dataType: 'json',
    cache: false,
    success :  function(result)
        {
            //pass data to datatable
            console.log(result); // just to see I'm getting the correct data.
            $('#test_table').DataTable({
                "searching": false, //this is disabled because I have a custom search.
                "aaData": [result], //here we get the array data from the ajax call.
                "aoColumns": [
                  { "sTitle": "ID" },
                  { "sTitle": "Name" },
                  { "sTitle": "Email" }
                ] //this isn't necessary unless you want modify the header
                  //names without changing it in your html code. 
                  //I find it useful tho' to setup the headers this way.
            });
        }
    });
});
</script>

test.php

This is the simple version I used for testing. My actual code is much more larger as it has several parts for querying and searching.

<?php

$columns = array( 
// datatable column index  => database column name
    0 => 'id',
    1 => 'name',
    2 => 'email',
);

$sql = "SELECT * FROM test_table";
$res = mysqli_query($conn, $sql) or die("Error: ".mysqli_error($conn));
$dataArray = array();
while( $row = mysqli_fetch_array($res) ) {


    $dataArray[] = $row["id"];
    $dataArray[] = $row["name"];
    $dataArray[] = $row["email"];

}

echo json_encode($dataArray);

?>

This simplifies things a lot, at least for me. I did not want to include additional libraries 'ssp.class.php'. I also did not want to get into PDO. So this has made it a lot more flexible and I hope it helps others who are trying to accomplish something similar.

Friday, November 11, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :