To run any background process from PHP you can simply use the exec() or shell_exec() functions. Adding a ‘&’ at the end causes the process can run in the background.
Create the php file to be executed
Put the php code you want to run in the background in a file called, for example, ‘my_background_task.php’
Execute it in the background
You’ll need the path to your php binary – see here.
$PathToFile = plugin_dir_path( __DIR__ ) . 'includes-functions/my-php-file-script-to-be-run.php';
//echo "[$PathToFile]<br>";
if (is_file($PathToFile))
{
//Get the path to the PHP binary
$PathToPhp = '/usr/bin/php';
//>>>>>
//Execute the file and capture the output (not in the background - useful for debugging)
//$Output = shell_exec("$PathToPhp $PathToFile 2>&1"); //"2>&1" means that STDERR is redirected into STDOUT (we get standard output or error output)
//echo "<pre>shell_exec() output:\n$Output</pre>";
//<<<<<
//Execute the file in the background
$ProcessId = shell_exec("$PathToPhp $PathToFile > /dev/null 2>&1 & echo $!"); //"2>&1" means that STDERR is redirected into STDOUT (we get standard output or error output),
//The " > /dev/null" is there because the output must be directed somewhere, /dev/null means it won't output it to a file
//The final "&" makes it execute in the background.
//The "echo $!" is there to get the process ID of the background process that was started.
echo "File run, ProcessId: $ProcessId<br>";
}
else
{
echo "File not found<br>";
}
Example ‘my-php-file-script-to-be-run.php’
#!/usr/bin/env php
<?php
echo "Some output\n";
echo "Some more output\n";
?>
Running a .php file with WordPress environment functionality
Say you want to run a wordpress task in the background, you can call a php file with it and use this to load the wordpress environment
#!/usr/bin/env php
<?php
//namespace MyNameSpaceName; //Optional, if you need to use the namespace in this file, otherwise remove
//----- LOAD WORDPRESS ENVIRONMENT -----
//We need the path to '/wp-load.php' which is before the '/wp-content' directory.
//__DIR__ will provide thepath to this directory, so adjust it to remove the extra
$Path = preg_replace( '/wp-content.*$/', '', __DIR__ );
require_once $Path . '/wp-load.php';
//----- FILES WE NEED TO INCLUDE -----
require_once $Path . 'wp-content/plugins/my-plugin-name/some-file-i-need.php';
//----- DO THE TASKS WE WANT TO RUN -----
//Simple test you have wordpress functionality:
echo(home_url() . "\n");
//Simple test you have wordpress database functionality
/*
global $wpdb;
//Example usage of $wpdb
$results = $wpdb->get_results("SELECT ID, post_title FROM {$wpdb->posts} WHERE post_status = 'publish' LIMIT 5");
echo "Top 5 Published Posts:\n";
foreach ($results as $post) {
echo "- ID: {$post->ID}, Title: {$post->post_title}\n";
}
*/
?>
Passing arguments to the PHP file
Executing it in the background
//----- SETUP THE ARGUMENTS WE'RE PASSING -----
$Arguments = ''
. 'my_field1=' . escapeshellarg($my_field1) . ' '
. 'my_field2=' . escapeshellarg($my_field2) . ' '
. 'my_field3=' . escapeshellarg($my_field3) . ' '
. 'my_field4=' . escapeshellarg($my_field4) . ' ';
//WHEN YOU EXECUTE THE SCRIPT, USE THIS
$ProcessId = shell_exec("$PathToPhp $PathToPhpFile $Arguments > /dev/null 2>&1 & echo $!");
In your ‘my-php-file-script-to-be-run.php’
//----- PARSE THE COMMAND LINE ARGUMENTS -----
//Remove script name
array_shift($argv);
$my_field1 = 0;
$my_field2 = '';
$my_field3 = '';
$my_field4 = '';
//Loop through CLI arguments
foreach ($argv as $Arg)
{
if (str_starts_with($Arg, 'metadata='))
{
$Raw = substr($Arg, strlen('metadata='));
// Match single "key":"value"
if (preg_match('/"([^"]+)":"([^"]+)"/', $Raw, $Match))
{
$metadata[$Match[1]] = $Match[2];
}
}
else if (str_contains($Arg, '='))
{
list($Key, $Value) = explode('=', $Arg, 2);
switch ($Key)
{
case 'my_field1':
$my_field1 = intval($Value);
break;
case 'my_field2':
$my_field2 = $Value;
break;
case 'my_field3':
$my_field3 = $Value;
break;
case 'my_field4':
$my_field4 = $Value;
break;
}
}
}
