はじめに
自作artisanコマンドで進捗がないと怖い
すでに公開しているWebサイトのデータベースの内容を加工したいとき、自作のartisanコマンドをサーバ上で実行することはよくあると思います。
しかし、対象データ数が多いために10分以上コンソールで何も表示がないまま待っていると、正常に実行されているか固まっているかの判断がつかずとても怖いです。ほんとに。
何のコマンドの進捗か、進捗率、最後まで処理できたかを表示
そこで必要な情報の表示を忘れないために、何のコマンドの進捗か、進捗率、最後まで処理できたかを表示の表示を行うサンプルを作ます。
コマンドのサンプル
- 実行したコマンドが正しいことを確認できるように最初にタイトルを表示
(正常に開始できたか、開始するときに指定したsignetureと実際の処理があっているかコンソール上で確認できます) - 多くのデータのループ処理はwithProgressBarのコールバックで実行して進捗表示
(このメソッドを使うだけでループ中に進捗表示が確認できるようになります) - すべて処理して終端にたどり着いたら
OK
を表示
(メモリ不足や他プロセスからのKILLで止まっていないことが確認できるようにするため)
app/Console/Commands/ExampleCommand.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class ExampleCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'example:command';
/**
* The console command description.
*
* @var string
*/
protected $description = 'コマンドのサンプル';
/**
* Execute the console command.
*/
public function handle()
{
/**
* コマンドを実行したときに、どのコマンドが実行されたか確認できるように最初にタイトルを表示
*/
$this->info('コマンドのサンプル : 開始'); // タイトル
/**
* サンプルデータ
* DBから取得したデータを想定
*/
$users = [ // ユーザの配列の例: Users::get()などでDBから取得したデータなどを想定
[
'name' => 'AAAAA', // ユーザ名
'elements' => array_fill(0, 12, '-'), // ユーザのなにかの要素: $user->immagesなどのリレーションを想定
],
[
'name' => 'BBBBBBB',
'elements' => array_fill(0, 10, '-'),
],
[
'name' => 'CCC',
'elements' => array_fill(0, 5, '-'),
],
[
'name' => 'DDDDD',
'elements' => array_fill(0, 8, '-'),
],
];
/**
* 処理のメイン
* データ単位ごとの実行する場合
*/
foreach ($users as $user) {
$this->taskUser($user);
}
/**
* コマンドの最後まで実行できたことが確認できるように最後にメッセージ出力
*/
$this->info('OK');
}
protected function taskUser($user)
{
$this->info("USER: {$user['name']}");
/**
* 要素ごとの処理
* 表示上で処理の進行が確認できるようにwithProgressBar()でループ処理をする
*/
$users = $this->withProgressBar($user['elements'], function ($element) use ($user) {
$this->taskUserElement($element);
});
$this->newLine();
}
protected function taskUserElement($element)
{
/**
* 要素ごとに処理
* element->update() などを想定
*/
////////////////////////
// ダミーの処理
sleep(1);
////////////////////////
}
}