How to run the PHP code asynchronous
Asked Answered
C

5

16

How can I run PHP code asynchronously without waiting? I have a long run (almost infinite) that should run while server starts and should process asynchronously without waiting.

The possible options I guess are:

  1. Running the code in a web page and keep it open to do that task
  2. Calling the script from some command line utility (I am not sure how) which would process in the background.

I am running the PHP scripts on my local server which will send emails when certain events occur, e.g. birthday reminders.

Please suggest how can I achieve this without opening the page in a browser.

Celestine answered 6/5, 2011 at 1:20 Comment(6)
The best bet is probably a cron job or daemon, but that's hard to determine without more details.Kimberykimble
Sounds like a web script is not what you meant to create.Higley
Almost and infinite are two words you can't really use next to each other. It's infinite or it's not, there is no such thing as almost infinite.Cochrane
"Almost there, just one more!" ad infinitum == infinite. ;o)Kimberykimble
What operating system is your server running?Kana
sorry If I could not explain properly. I am using Windows with Apache/MYSQL/PHP. @Cochrane the task is infinite only as I described its purpose is to send the emails by checking the tasks.Celestine
D
26

If you wanted to run it from the browser (perhaps you're not familiar with the command line) you could still do it. I researched many solutions for this a few months ago and the most reliable and simplest to implement was the following from How to post an asynchronous HTTP request in PHP

<?php


$params['my_param'] = $a_value;
post_async('http:://localhost/batch/myjob.php', $params);

/*
 * Executes a PHP page asynchronously so the current page does not have to wait for it to     finish running.
 *  
 */
function post_async($url, array $params)
{
    foreach ($params as $key => &$val) {
      if (is_array($val)) $val = implode(',', $val);
        $post_params[] = $key.'='.urlencode($val);  
    }
    $post_string = implode('&', $post_params);

    $parts=parse_url($url);

    $fp = fsockopen($parts['host'],
        isset($parts['port'])?$parts['port']:80,
        $errno, $errstr, 30);

    $out = "POST ".$parts['path']." HTTP/1.1\r\n";
    $out.= "Host: ".$parts['host']."\r\n";
    $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
    $out.= "Content-Length: ".strlen($post_string)."\r\n";
    $out.= "Connection: Close\r\n\r\n";
    if (isset($post_string)) $out.= $post_string;

    fwrite($fp, $out);
    fclose($fp);
}

Let's say the file above is in your web root directory (/var/www) for example and is called runjobs.php. By visiting http://localhost/runjobs.php your myjob.php file would start to run. You'd probably want to add some output to the browser to let you know it was submitted successfully and it wouldn't hurt to add some security if your web server is open to the rest of the world. One nice thing about this solution if you add some security is that you can start the job anywhere you can find a browser.

Daft answered 6/5, 2011 at 3:9 Comment(3)
There is nothing asynchronous about this. You are simply writing to a socket, and then closing that socket without waiting for a response. Asynchronous would be creating a new thread or something that sits and waits for a response from the curl request and ensures the request was received.Robot
Not getting a response might not be ideal in some situations, but this is definitely asynchronous: "Asynchronous actions are actions executed in a non-blocking scheme, allowing the main program flow to continue processing."Daft
In case you need HTTP_GET, replace $out = "POST ".$parts['path']." HTTP/1.1\r\n"; by if (!empty($parts['query'])) { $query = "?".$parts['query']; } $out = "GET ".$parts['path']." HTTP/1.1\r\n";Omnipotence
M
4

Definitely sounds like a job for a cron task. You can set up a php script to do your task once and have the cron run as often as you like. Here's a good writeup on how to have a php script run as a cron task; it's very easy to do.

Midweek answered 6/5, 2011 at 2:57 Comment(1)
This is a very common solution to a very common problem. Most PHP programs with recurring events (software update checks, birthday reminders, etc) have a "cron.php" script which is run from a crontab, either via a program like "wget" or "curl", or directly via command line execution. This way, you don't need to keep the script running all the time, and can let it quit as soon as the task is done. It will be called again at some interval after all.Woke
K
0

This isn't really what PHP is designed for. You have to use the PECL threading library to spin off threads that run asynchronously, and I don't recommend it. The new hotness in the async department is node.js - I recommend you look into that and see if you can utilize it. It's designed for light weight, asynchronous network operations, and can be used to fire PHP scripts.

Kilkenny answered 6/5, 2011 at 1:49 Comment(1)
The question seems to be about something that is much better suited for a normal shell environment, not a web server, so probably NodeJS and asynchronous web request handling won't be needed.Kana
S
0

How Can I run PHP code asynchronously without waiting. I have a long run (almost inifinite) that should run while server starts and should process asynchrously without waiting.

Assuming a typical LAMP system, you can start a PHP daemon from the command line with

root# php yourscript.php &

where yourscript.php contains something similar to

<?php

$log = fopen('/var/log/yourscript.log', 'a+');
// ### check if we are running already omitted
while(true) {
    // do interesting stuff and log it.

    // don't be a CPU hog
    sleep(1);
}
?>

Embellishments: To make your script directly executable: chmod +x yourscript.php and add #!/usr/bin/php to the beginning of yourscript

To start with apache, you should add that command to your apache startup script (usually apachectl) and be sure to add code to kill it when apache stops.

The check if you are already running involves a file with your PID in /var/locks/ and something like system('/bin/ps '.$thePID); It also makes the kill instruction easier to write.

Scandura answered 6/5, 2011 at 2:50 Comment(0)
D
0

thanks Todd Chaffee but it is not working for me so i edited your code i hope you will not mind and may be it will also help others with this technique

cornjobpage.php //mainpage

     <?php
//if you want to call page for multiples time w.r.t array 
//then uncomment loop start & end)
?>

<?php
//foreach ($inputkeywordsArr as $singleKeyword) {
    $url="http://localhost/projectname/testpage.php";
        $params['Keywordname'] = "testValue";//$singleKeyword 
        post_async($url, $params);

        //}//foreach ($inputkeywordsArr end
        ?>
        <?php

        /*
         * Executes a PHP page asynchronously so the current page does not have to wait for it to     finish running.
         *  
         */
        function post_async($url, array $params)
        {
            foreach ($params as $key => &$val) {
              if (is_array($val)) $val = implode(',', $val);
                $post_params[] = $key.'='.urlencode($val);  
            }
            $post_string = implode('&', $post_params);

            $parts=parse_url($url);

            $fp = fsockopen($parts['host'],
                isset($parts['port'])?$parts['port']:80,
                $errno, $errstr, 30);

            $out = "GET ".$parts['path']."?$post_string"." HTTP/1.1\r\n";//you can use POST instead of GET if you like
            $out.= "Host: ".$parts['host']."\r\n";
            $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
            $out.= "Content-Length: ".strlen($post_string)."\r\n";
            $out.= "Connection: Close\r\n\r\n";
            fwrite($fp, $out);
            fclose($fp);
        }
        ?>

testpage.php

    <?
    echo $_REQUEST["Keywordname"];//Output > testValue
    ?>
Dehlia answered 19/12, 2016 at 14:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.