PHPのプログラム内に重い処理を実行する部分がある場合、普通はその処理が終わるまでプログラムは先に進みません。でも、処理だけさせておいて、プログラムを先に進めたい場合もあると思います。

 今回は、そんな重い処理をバックエンドで実行させる簡単な方法をご紹介します。このやり方はLinux/Unix環境で使えます。

時間がかかるスクリプトの例(test.php)
<?php
/* POSTされた時に、時間がかかる処理が走る。ここでは何もせずに10秒ストップ*/
if ($_POST['submit']) {
  
sleep(10);
  echo 
'finish!';
} else {
?>
<html>
重い処理が走るスクリプト
<form method="post" action="test.php">
<input type="submit" name="submit" value="重い処理を実行">
</form>
</html>
<?php
}
?>

 このスクリプトにアクセスしてボタンを押すと、10秒たたないとfinish!の文字が表示されません。

 そこで、処理の部分を別プログラムに分けます。

重い処理を行うスクリプト(/path/to/exec.php)
<?php
sleep
(10);
?>

待たされないスクリプト(test2.php)
<?php
if ($_POST['submit']) {
  
exec("/usr/local/bin/php /path/to/exec.php > /dev/null &");
  echo 
"とりあえず finish!";
} else {
?>
<html>
重い処理が走るけれど、待たされないスクリプト
<form method="post" action="test2.php">
<input type="submit" name="submit" value="重い処理を実行">
</form>
<?php
}
?>

 exec関数を使って、プログラム内でさらにコマンドラインでPHPのプログラムを実行します。

 コマンドの最後に「 > /dev/null &」をつけるのがポイントです。exec関数引数の、/usr/local/bin/phpと、/path/to/exec.phpは環境に応じて正しくパスを指定する必要があります。

 処理を実行するスクリプトに引数を渡して使う場合は、次のようにします。

引数を受け取って重い処理を実行するスクリプト(/path/to/exec2.php)
<?php
//引数を2つ入手。$argv配列に順番に入る。
$str1 $argv[1];
$str2 $argv[2];
...


//待たされないスクリプト
<?php
if ($_POST['submit']) {
  
$str1 'hoge';
  
$str2 'fuga';
  
//一応エスケープ処理
  
$q_str1 escapeshellarg($str1);
  
$q_str2 escapeshellarg($str2);

  
$cmd '/usr/local/bin/php '$q_str1 .' '$q_str2 .' > /dev/null &';
  
exec($cmd);
...

 これで、ユーザ入力等をバックエンドのプログラムに渡すことも可能です。ユーザ入力を扱う時は、必ず最低限のエスケープ処理を入れるようにしましょう。



(アシアル 牧野克俊)


この記事は、アシアルが運営するPHP開発者のためのポータル&コミュニティサイト「PHPプロ!」で毎週配信しているPHP・TIPSメーリングリストを再録したものです。
同サイトでは、他にもPHP最新ニュースや、困ったときのQ&A掲示板、初心者向けのPHP講座など、PHP開発者をサポートする情報を掲載しています。