やりたいこと
フレームワークのタスクなどを実行する際に、きちんと進行しているかインジケータを表示させたい。ただし、処理数分だけ行数を重ねるのではなくて1行に上書きしていきたい。上手く説明できなくて歯がゆいんですけど、つまりこうではなくて、doSomething ... 1/5
doSomething ... 2/5
doSomething ... 3/5
doSomething ... 4/5
doSomething ... 5/5 finished
こう。
doSomething ... 5/5 finished ← この行だけで更新されていく
わかりますかね…
解法:改行ではなく「キャリッジリターンを使う」
「キャリッジリターン」というのはカーソルを行末から行頭に戻すためのコードで改行コードを含まないので、そのコードまで行くとカーソルは同じ行の先頭に移動して入力を待ちます。で、次の行が入力されると前の行の上に上書きされます、と。キャリッジ・リターン – Wikipedia
これを知る前は次のようなコードを書いていて、上のように処理数分行が表示されていました。
$STDOUT = fopen("php://stdout", "w");
fwrite($STDOUT, $message . PHP_EOL);
fclose($STDOUT);
文字列を標準出力に書き出して、改行。
これをこうすれば、1行が更新されていく処理が表現できます。
$STDOUT = fopen("php://stdout", "w");
fwrite($STDOUT, $message . "\r");
fclose($STDOUT);
1つの処理が完了したら次の処理…という風にしたい場合には、何かフラグを与えて、
$STDOUT = fopen("php://stdout", "w");
fwrite($STDOUT, $message . (($finished) ? PHP_EOL : "\r"));
fclose($STDOUT);
とすればいいのかな。
実行ログはこんな感じで表示されていきます。
doSomething ... 5/5 finished
doNextTask ... 23/23 finished
doLastTask ... 49/49 finished
どう考えてもCUIの基礎だなあ。
俺ってホントに何も知らないんだなと思いました。メモ。