Using pcntl_fork() allows for forking of a running processing in PHP. In this example I fork my shell script and process data and return the results. This would be useful in a case where you had to make api calls to lets say 4 vendors: amazon, itunes, youtube, flickr. You would assign each child id a task to run. They each would then write there results to a shared memory location for further manipulation. I have written this test in CakePHP shell script.
class ForkShell extends AppShell {
public function main() {
$total = 0;
$data = array();
$result = array();
$start = (float) array_sum(explode(' ', microtime()));
echo "Parent PID: ".getmypid().PHP_EOL;
$this->forkTest($data);
// Manipulate the results from the fork
foreach ($data as $key => $value) {
$total = $total + $value['number'];
}
$result['sum_of_digits'] = $total;
$result['data'] = $data;
echo "Processing time: ".sprintf("%.4f", ((float) array_sum(explode(' ', microtime())) - $start))." seconds".PHP_EOL;
print_r(Set::reverse($result));
}
public function forkTest(&$data = array()) {
$pids = array();
$parent_pid = getmypid();
for ($i = 0; $i < 4; $i++) {
if (getmypid() == $parent_pid) {
$pids[] = pcntl_fork();
echo "Forking child, now has ".count($pids)." elements".PHP_EOL;
}
}
if (getmypid() == $parent_pid) {
// Process children results as they exit, but not before
while (count($pids) > 0) {
echo "Parent id: ".getmypid().PHP_EOL;
// Wait for child to complete / maintains consistency
$pid = pcntl_waitpid(-1, $status);
// Open shared memory block (read only)
$shm_id = shmop_open($pid, "a", 0, 0);
// Read data based on chunk size to local variable
$shm_data = unserialize(shmop_read($shm_id, 0, shmop_size($shm_id)));
// Delete shared memory block
shmop_delete($shm_id);
// Close shared memory block
shmop_close($shm_id);
// Merge data to memory location of data
$data = array_merge($data, $shm_data);
/* Remove all PID entries created */
foreach ($pids as $key => $tpid) {
if ($pid == $tpid) {
unset($pids[$key]);
}
}
}
$pids = array();
} else {
echo "Child id: ".getmypid().PHP_EOL;
// From here you could do API calls or other calculations and bring the results together
$pdata = array();
array_push($pdata, array(
'child_id' => getmypid(),
'number' => rand(5, 15)
));
$data_str = serialize($pdata);
// Open shared memory location
$shm_id = shmop_open(getmypid(), "c", 0644, strlen($data_str));
// attempt to write to shared memory
if (!$shm_id) {
exit("Couldn't create shared memory segment");
} else if (shmop_write($shm_id, $data_str, 0) != strlen($data_str)) {
exit("Couldn't write shared memory data");
}
exit(0);
}
}
}
I would not recommend running this script inside of CakePHP. It may cause issues with the caching.