はい。
これは、HTTPヘッダーを正しく利用すれば、非同期処理なしで簡単に実行できます。
通常の状態では、PHPは、もう一方の端のクライアントが接続を閉じるとすぐに処理を停止します。このイベントの後で処理を続行する場合は、1つのことを行う必要があります。ユーザーの中止を無視するようにPHPに指示します。どのように?
ignore_user_abort()
これにより、クライアントが回避から抜け出した後でも、スクリプトを実行し続けることができます。しかし、接続を閉じるために、クライアントが行った要求が終了したことをクライアントに通知する方法の問題にも直面しています。通常、PHPは、これらのヘッダーを指定しない場合、これらのヘッダーの送信を透過的に処理します。ただし、ここでは明示的に行う必要があります。そうしないと、クライアントは応答の読み取りをいつ停止するかがわかりません。
これを行うには、適切なHTTPヘッダーを送信して、クライアントにいつ閉じるかを通知する必要があります。
Connection: close
Content-Length: 42
このヘッダーの組み合わせは、42バイトのエンティティ本体応答を読み取ると、メッセージが終了し、接続を閉じる必要があることをクライアントに通知します。この方法にはいくつかの結果があります。
- 正しいヘッダーを送信できるようにコンテンツの長さのサイズをバイト単位で決定する必要があるため、出力を送信する前に応答を生成する必要があります。
- 出力をエコーする前に、これらのヘッダーを実際に送信する必要があります。
したがって、スクリプトは次のようになります。
<?php
ignore_user_abort();
// do work to determine the response you want to send ($responseBody)
$contentLength = strlen($responseBody);
header('Connection: close');
header("Content-Length: $contentLength");
flush();
echo $responseBody;
// --- client will now disconnect and you can continue processing here ---
この方法の大きな「Gotchya」は、Web SAPIでPHPを実行しているときに、エンドユーザークライアントが接続を閉じた後に時間のかかる処理を行うと、maxtimelimitディレクティブに簡単にぶつかることができることです。これが問題になる場合は、PHPをCLI環境で実行するときに時間制限がないため、cronを使用した非同期処理オプションを検討する必要があります。set_time_limit
または、ドキュメントを使用して、Web環境でのスクリプトの制限時間を延長することもできます。
このようなことを行う場合は、応答本文の生成中にconnection_aborted()
ドキュメントにチェックを追加して、ユーザーが転送を完了する前に中止した場合に追加の処理を回避できるようにすることもできます。