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;
        }
    }
  }