CakePHPで画面表示後に処理を続ける方法

CakePHPで先に画面を表示した後に何らかの後処理を続けたい事があると思います。

例えば外部APIのコールや集計処理、少し重い処理等々。

よく紹介されているのがシェルスクリプトを起動したり自分をHTTP(S)アクセスする方法ですが、それらの方法を採りたくない(採れない)という事もあるかと思います。

CakePHPで画面表示後の後処理を行うちょっとトリッキーな方法を紹介します。

レスポンスを用意した後、afterFilter等で以下のようにResponseEmitterを直接呼び出すだけです。

use Cake\Http\ResponseEmitter;

use Cake\Event\EventInterface;

public function afterFilter(EventInterface $event)
{
    // クライアントにレスポンスを返して接続切断
    $emitter = new ResponseEmitter();
    $emitter->emit($this->getResponse());

    // 続けたい処理
    sleep(10);
}

先頭はResponseEmitterを使用するためのuseです。

emitで渡したレスポンスがクライアントに返り、クライアントとの接続が切断されます。

その後に続けたい後処理を書くことで実現できます。

注意点としては以下のような事が挙げられますので注意して下さい。

  • ヘッダを送った後にヘッダを送ってる系の警告が出る事がある
  • 時間のかかる後処理は次のリクエストを処理できるまで時間がかかるので、リクエストの多い環境ではプロセスを食いつぶしてしまう可能性が高くなる
  • CakePHP 4で調査したので3.xでは未検証(3.xでも4に近いバージョンなら可能、もしくは似た方法があるかもしれない)
  • emitはfastcgi_finish_request()を使用しているだけなので、直接fastcgi_finish_request()を呼べば自作も可能

後処理のためにコマンドを叩いたりhttpリクエストを投げたくない人は試してみて下さい。