ブラウザの中止ボタンを押した後も処理を実行させる方法 タイムアウト以外の停止

PHPはブラウザの読み込み中止ボタン(読み込み停止ボタン)をクリックしたり、閉じるボタンで閉じてしまうと処理が途中で止まります。
またブラウザとのネットワークが切れてしまったときにも止まります。
つまり出力処理を受ける相手がいなくなるまたは反応がなくなると、処理を中断します。

そこでブラウザを閉じたり、ネットワークが切れたときでも処理を続行させるには次のようにします。

ignore_user_abort(true);

ここで処理に時間がかかってしまったときでもタイムアウトしないようにするには、タイムアウトを無制限にします。

[参考記事] PHPタイムアウトの対処法

ignore_user_abort(true);
set_time_limit(0);

ただしこの場合は無限ループにならないように注意します。

このignore_user_abort()は、php.iniのignore_user_abortに値を渡す関数です。
つまりphp.iniの設定でも可能で、ignore_user_abortはPHP_INI_ALLなので.htaccessなどでも設定可能です。

php.iniやhttpd.conf

ignore_user_abort "1"

.htaccess

php_value "ignore_user_abort" "1"

ignore_user_abortの値が『0』だったとき、つまりデフォルト状態だったとき、どのタイミングで処理が止まるかというと、標準出力を受ける相手(ブラウザ)が受けとらなかったとき(破棄されたとき)です。
ブラウザの閉じるボタン、中止ボタンを押したときではありません。
なぜなら閉じるボタン、中止ボタンを押したときにサーバに信号を送らないため、サーバ(PHP)側にはわからないからです。

標準出力を送ったタイミングに判断されるというのは、正確にはechoをしたときではありません。
PHPではネットワークI/O負荷を軽減させるため、一定の出力をまとめてブラウザなどに送信します。(バッファリング)
flush()などを実行すると、このタイミングを制御することができます。

またクライアントの接続が切断される動作はブラウザ(クライアント)にもよりますが次のようなものがあります。
(1)ネットワークが切れたとき
(2)ブラウザの閉じるボタンを押したとき
(3)ブラウザの中止ボタンを押したとき
(4)別のページに移動したとき

PHPによる出力が遅い場合・処理が長い場合、プロキシなどネットワークがタイムアウトし切断されることもあります。

ignore_user_abortを『1』にしていても、コマンドラインで実行していた場合はttyが消えると、標準出力をしたときに処理が止まります。

ブラウザなどとの接続状態を知る関数もあるので、ignore_user_abortを『1』にしていたときの接続状態での振る舞いを制御することができます。
(ignore_user_abortの値が『0』のときには意味がありません。)

クライアントとの接続が切れているかどうかを知るには、connection_aborted()の戻り値が『1』なら切れている、『0』ならそれ以外となります。
connection_aborted()はこの2つしかありませんが、connection_status()を使うと、より詳しく知ることができます。

connection_status()の戻り値

定数状態
CONNECTION_NORMAL0アクティブ
CONNECTION_ABORTED1リモートクライアントが接続を切った
CONNECTION_TIMEOUT2PHP 側の時間制限にかかった

これを利用すると、ブラウザが閉じたときなどに処理を実行させるということもできます。

<?php
// ユーザによる中断を無視する
ignore_user_abort(true);
// タイムアウトしないようにする
set_time_limit(0);

// 無意味なループを繰り返す
// 他のページに移動したり、"中止"ボタンを押すまでループする
while(1)
{
  // 出力が破棄されたときループを抜ける
  if(connection_status() != CONNECTION_NORMAL){
    break;
  }

  // 10 秒間停止
  sleep(10);

  echo str_pad('',1);
  flush();
}

// ここで、ブラウザが閉じたときなどの処理を行います

関連記事

スポンサーリンク

TRUNC関数 切り捨て

ホームページ製作・web系アプリ系の製作案件募集中です。

上に戻る