PHPプロ!TIPS+

重い処理をバックエンドで実行する

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);
...

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

バックナンバーについて

TIPS-MLは、毎週金曜日に更新され、新しい記事が掲載されます。

Tipsꗗy[W 

Pick Up Q&A

Q
PHPのHTML埋め込み記述について
 このエントリーをはてなブックマークに追加 
A
$_POST["data"] == "男" ? $val = "checked" : $val = "" ; の意味は以下と同じです。 if($_POST["data"] == "男"){ $val = "checked; } e...

>>続きを読む

kende様のご指摘通り、三項演算子を使用する際には、コードの複雑度などを考慮する必要がありますね。書きやすさと共に可読性も追求したいところですね。

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)