PHPからバックグラウンド処理を実行させる(その2)

うまくいっていたのに、その後いろいろ試してみると、やっぱり時間がかかっている。待たされ感がある。バックグラウンドプログラムをコールするのは上手くないのかもしれない。

PHPからバックグラウンド処理を実行させる

ウェブ画面のレスポンスはどれだけ遅くても数秒程度で帰ってきて欲しい。しかし時間がかかる処理というものもある。その時はフロントエンドの画面では「処理を開始しました」と表示しておき、バックグラウンドで実行プログラムを起動する方法が有効。

PHPの場合、exec関数を使えば、PHPでもJavaでもシェルでもなんでも呼び出せる。

その呼び出し方だが普通に以下のようにコールするのはまずい。

exec(‘/usr/bin/php program.php’);

これだと、program.phpが終了するまで、フロントエンドは待たされることになる。つまりバックグラウンドになっていない。

exec(‘/usr/bin/php program.php &’);

「&」をつけてバックグラウンドで処理しろっ。でもだめ。これでも待たされることになる(これはなぜだかわからないんだけど、実際そうなる)。

exec(‘/usr/bin/php program.php >/dev/null 2>&1′);

正解はこれ。別にリダイレクト先は/dev/nullでなくてもよいし2>&1もなくてもOK。とにかく出力しない、ってことにしておけばよさそうだ。

一応マニュアルにも書いてある。

プログラムがこの関数で始まる場合、 バックグラウンドで処理を続けさせるには、 プログラムの出力をファイルや別の出力ストリームにリダイレクトする必要があります。 そうしないと、プログラムが実行を終えるまで PHP はハングしてしまいます。

文章分かりにくい。まぁ、確認の意味も兼ねて、実証してみた。

n進数に変換

ユーザに一意な値を割り当てたいときがある。将来永劫にわたって同じ値は使いたくない。こんなとき一番便利なのはmicrotime関数でUNIXタイムスタンプ値を少数単位まで算出してやればだいたい問題なさそう。ただ、整数部分だけでも10桁あり、例えば少数第4位まで使用するにしても、合計で14桁の数値(文字列)を使わなければならない。これではちょっと長すぎて使いづらい。

そこで思いついたのだが、各桁で使用する数字が10種類(0、1、2、3・・・)しかないから14桁も必要になるわけで、使用する文字種を増やしてやればもっと小さな桁数で表現することができる。数字は10種類あるので、これにアルファベット26文字を足せば合計36種類になる。つまり10進数を36進数で表現すれば文字列の桁数を減らすことができる。

進数の変換をするための関数が用意されている。base_convert関数だ。

この関数を使って14桁の数値(10進数)を36進数に変換すると9文字の英数字に変換してくれる。5文字のお得となる訳だ。ただし、base_convert関数は、極端に大きな数を対象とする場合は誤差が生じるらしい。おおむね14桁の精度らしいが、OSに依存するようだ。

変換関数を作らなければならないと思っていたけど、とりあえずこれで使うことにする。

8ビットの文字をメールで送信するとき

あまり文字のことで悩みたくないが、中国語のメール送信プログラムを書いたときのメモ。

タイトル等ヘッダに関する部分は英語記述で対応することにした。マルチバイトな文字が関係しなければ悩む必要なし。

中国語だと本文は当然漢字になる。日本語みたいにISO-2022-JPに変換しちゃえばいい、という具合でもなさそう。結局こんな具合で送信することにした。

  • 本文($body)はUTF-8とする
  • このままだと8bitでメールを送る可能性があるのでimap_8bit関数で変換した。
    $body=imap_8bit($body);
    ただしimap_8bit関数はIMAPモジュールが必要になる(PHP4以上で使える)。
    PHP5.3以上ならquoted_printable_decode関数のほうがいいかも。

メールヘッダも小細工が必要で、以下のヘッダを付与した。

  • MIME-Version: 1.0
  • Content-Type: text/plain; charset=utf-8
  • Content-Transfer-Encoding: quoted-printable

MIME-Versionは必要ないかもしれない。だけど参考にしたメールソフトではついていたので、とりあえずつけておいた。

MySQL使用時のtimezoneの設定

この前PHPのtimezoneの設定について記述した。この設定は当然PHPスクリプトのみで有効だ。MySQLと連携したシステムを作って、SQL文に日付関連の関数を組み込んだ場合、PHPに処理が渡る前にデータベース操作が終わってしまう。となると、データベース操作で得られる値は、期待したtimezoneでの値とは異なるものになる可能性が高い。そんな時に使うのがこれ。

SET time_zone = ‘+9:00′;

MySQL使用時に「SET NAMES binary;」というおまじないを付ける人も多いと思う。文字化け関連に対応するためにつけるわけだが、やっていることはこれと同じ。「SET」によって環境を設定している。つまりこれにより、一時的にtimezoneに変更を加えることができる。だからPHPからSQL文を発行するときに、毎回このSQL文を一番最初に発行しておいてやれば良さそうだ。

どんな具合に適用されるのかは、しばらく使ってみて確かめることにする。


守谷市(まちの情報ポータル) 無料アンケートレンタルjpForm.net