Problem
I have a form that, when submitted, will run basic code to process the information submitted and insert it into a database for display on a notification website. In addition, I have a list of people who have signed up to receive these notifications via email and SMS message. This list is trivial as the moment (only pushing about 150), however it's enough to cause it takes upwards of a minute to cycle through the entire table of subscribers and send out 150+ emails. (The emails are being sent individually as requested by the system administrators of our email server because of mass email policies.)
During this time, the individual who posted the alert will sit on the last page of the form for almost a minute without any positive reinforcement that their notification is being posted. This leads to other potential problems, all that have possible solutions that I feel are less than ideal.
First, the poster might think the server is lagging and click the 'Submit' button again, causing the script to start over or run twice. I could solve this by using JavaScript to disable the button and replace the text to say something like 'Processing...', however this is less than ideal because the user will still be stuck on the page for the length of the script execution. (Also, if JavaScript is disabled, this problem still exists.)
Second, the poster might close the tab or the browser prematurely after submitting the form. The script will keeping running on the server until it tries to write back to the browser, however if the user then browses to any page within our domain (while the script is still running), the browser hangs loading the page until the script has ended. (This only happens when a tab or window of the browser is closed and not the entire browser application.) Still, this is less than ideal.
(Possible) Solution
I've decided I want to break out the "email" part of the script into a separate file I can call after the notification has been posted. I originally thought of putting this on the confirmation page after the notification has been successfully posted. However, the user will not know this script is running and any anomalies will not be apparent to them; This script cannot fail.
But, what if I can run this script as a background process? So, my question is this: How can I execute a PHP script to trigger as a background service and run completely independent of what the user has done at the form level?
EDIT: This cannot be cron'ed. It must run the instant the form is submitted. These are high-priority notifications. In addition, the system administrators running our servers disallow crons from running any more frequently than 5 minutes.
So, to run any background process from PHP, we can simply use either exec or shell_exec function to execute any terminal command and in that command, we can simply add & at the last so that, the process can run in the background.
You can put a task (such as command or script) in a background by appending a & at the end of the command line. The & operator puts command in the background and free up your terminal. The command which runs in background is called a job. You can type other command while background command is running.
PHP is server-side which mean it executes on server. While handling request, first PHP is executed, that the response is returned to user, and then Javacript executes. To communicate between client and server you can use ajax requests, which are basically simple http requests but without reloading whole page.
Use isset() method in PHP to test the form is submitted successfully or not. In the code, use isset() function to check $_POST['submit'] method. Remember in place of submit define the name of submit button. After clicking on submit button this action will work as POST method.
The bad news is, PHP is not quite made to run in the background “by default”. But thankfully, there are a few simple alternatives. To run PHP scripts in the background, we can either use the popen () or exec () function to run another PHP script in the command line. Of course, this is a simplification of what can be done.
When we need to run some script without waiting the fronted user till the process is not completed, For that we need to execute some script in background to hiding the execution time to user.This process is hidden to the end user. It improves your Website efficiency.
The concept, In LINUX there is a shell script which is used to run the process in background. You can put a task (such as command or script) in a background by appending a & at the end of the command line.
We create a PHP script to run a PHP script in the command line. Yes, simply access 1b-run.php and check if the dummy.txt file is generated on the server. P.S. Make sure that PHP has permission to run the commands or this will fail.
Doing some experimentation with exec
and shell_exec
I have uncovered a solution that worked perfectly! I choose to use shell_exec
so I can log every notification process that happens (or doesn't). (shell_exec
returns as a string and this was easier than using exec
, assigning the output to a variable and then opening a file to write to.)
I'm using the following line to invoke the email script:
shell_exec("/path/to/php /path/to/send_notifications.php '".$post_id."' 'alert' >> /path/to/alert_log/paging.log &");
It is important to notice the &
at the end of the command (as pointed out by @netcoder). This UNIX command runs a process in the background.
The extra variables surrounded in single quotes after the path to the script are set as $_SERVER['argv']
variables that I can call within my script.
The email script then outputs to my log file using the >>
and will output something like this:
[2011-01-07 11:01:26] Alert Notifications Sent for http://alerts.illinoisstate.edu/2049 (SCRIPT: 38.71 seconds) [2011-01-07 11:01:34] CRITICAL ERROR: Alert Notifications NOT sent for http://alerts.illinoisstate.edu/2049 (SCRIPT: 23.12 seconds)
On Linux/Unix servers, you can execute a job in the background by using proc_open:
$descriptorspec = array( array('pipe', 'r'), // stdin array('file', 'myfile.txt', 'a'), // stdout array('pipe', 'w'), // stderr ); $proc = proc_open('php email_script.php &', $descriptorspec, $pipes);
The &
being the important bit here. The script will continue even if the original script has ended.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With