tvirelli
tvirelli

Reputation: 464

How can I execute a PHP script from PHP without keeping the user on the page?

I have a script to process sending emails. There could be thousands of emails to send. I want to show the user a page that says something along the lines of "Your messages are being sent.", but I don't want that page to do the actual sending of the messages, because I don't want the user to see a blank page until the script finishes and I also don't want the user to have to wait for the script to finish.

I would like to pass a list of IDs to another PHP page (lets call it run.php) and have it execute without having the user actually visit it. So I would pass the IDs to the page, which starts the execution, but then finishes loading the current page which shows the message "Your messages are being sent.".

<?php
/* SESSION DATA HERE */
executeMailSend($ids);
?>
<html>
<head>
....
</head>
<body>
Your messages are being sent.
</body>
</html>

I think I could something like this using ajax, but I would prefer to not make this rely on client side coding.

Also, if at all possible, I need to have the script running in the background keep session data from the session that starts it, and I would prefer that I don't have to pass this data along as separate variables.

Also, I don't want to use anything like exec() or system().

Any ideas?

Upvotes: 0

Views: 539

Answers (6)

JSON
JSON

Reputation: 1835

Are you on Linux server? You can fork() the script (within PHP) then daemonize the child process, detaching it so that it continues to run after the initializing HTTP request is finalized. Just make sure to kill the child processes correctly.

http://www.re-cycledair.com/php-dark-arts-daemonizing-a-process

Upvotes: 0

tvirelli
tvirelli

Reputation: 464

I guess I will have to stick with my current option which is script I've used before. I was hoping to find a better option, but here is the code I am going to use:

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

    if (!$fp) {
        return false;
    } else {
        $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($parts['query'])."\r\n";
        $out.= "Connection: Close\r\n\r\n";
        if (isset($parts['query'])) $out.= $parts['query'];

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

backgroundPost($siteURL.'/run.php?ids='.urlencode($ids).'&sessiondata='.urlencode($sessiondata));

Does anyone see a problem with using this? Security, bad code, etc?

Upvotes: 0

Matt
Matt

Reputation: 5567

A cron job is one option. You could do it by implementing a queue in the database, you'd just add entries for the mail to be sent and the cron job processes those entries. But maybe read this before going down that road: http://www.engineyard.com/blog/2011/5-subtle-ways-youre-using-mysql-as-a-queue-and-why-itll-bite-you/

If you use a cron job, you're going to be implementing a queue somewhere (flat file...blech, MySQL, other DB, etc.)

Why not use something that is actually made for queuing? For example you could use Amazon (http://aws.amazon.com/sqs/). But whatever software/provider you use, this sounds like it would be best with proper job queuing. You want the user to go to a page which will add some work items to your queue (which in this case are email addresses and maybe messages depending on exactly what you are doing). Then the queue software should have some means of processing these jobs (i.e. actually sending the emails).

You say you don't want to pass variables, but you'd likely have to send whatever data you need for each job to your queue. You could potentially store extra data to your database, just think about locking and performance.

Upvotes: 1

Daryl Gill
Daryl Gill

Reputation: 5524

if you have access to a linux box; you can use something called Cronjobs.

You can create a separate script with it's own database table, which it uses for reference.

on a set interval it runs PHP through the linux CLI for PHP and executes the script, no user needs to be on the page. the database needs to be configured properly though.

Only problem is with cronjobs, all output is emailed to the administration E-mail (/etc/aliases

Example on Cronjob input:

nano /etc/crontab

* * * * *  root /usr/bin/php /var/www/cron.php 

and on your cron.php you will have a script setup for a specific function, in this case. E-mail users.

http://www.thegeekstuff.com/2011/07/php-cron-job/

Upvotes: 0

user2742648
user2742648

Reputation:

You could make your script add that email to 'email query' and schedule a cron job to send emails. I don't think there is other way to call php script asynchronously.

Maybe this could point you in right direction: http://blog.markturansky.com/archives/205

Upvotes: 0

Darwayne
Darwayne

Reputation: 1420

Utilize the power of AJAX for more information checkout this tutorial by w3schools.com

http://www.w3schools.com/ajax/default.asp

Upvotes: 1

Related Questions