はじめに
Laravelの artisan
コマンドは、実際にはバッチの開発などで使う機会が多いと思いますが、コンソール向きのコマンドも、Laravelから用意された機能を組み合わせることで、開発しやすくなっています。
今回は、 artisan
コマンドを使用した、コンソール向きのコマンドの作成方法を紹介します。
コマンドの作成方法
コマンドを作成するには、下記コマンドを実行します。
$ php artisan make:command CommandName
app>Console>Commands
配下に、コマンド用のクラスが作成されます。
コマンドの実装
コマンドを生成すると、以下のコードが生成されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <?php namespaceApp\Console\Commands; useIlluminate\Console\Command; classHelloExampleextendsCommand { /** * The name and signature of the console command. * * @var string */ protected$signature='command:name'; /** * The console command description. * * @var string */ protected$description='コマンドのサンプルです'; /** * Create a new command instance. * * @return void */ publicfunction__construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ publicfunctionhandle() { // } } |
$signature
にコマンド名を指定します。実際にコマンドを実行する際は、 $ php artisan command:name
となります。
また、 $description
には、コマンドの説明を書きます。ここに書いた説明は、 $ php artisan list
コマンドを実行した時に表示されます。
__construct()
メソッドは、主にコンストラクタインジェクションとして活用することができます。今回は説明を省略しますが、コマンドのロジックは、Service化しておくことで、取り回しの良いコードになると思います。handle()
メソッドに、実際にコマンドが実行された時の処理を書きます。コマンドの引数やオプションも、このメソッド内で受け取ります。
以降、 handle()
メソッド内での、コマンドの実装方法について、紹介したいと思います。
文字列出力
シンプルにコンソールに出力するには、以下のように実装します。
1 | $this->line('こんにちは'); |
この他にも、出力したい内容別にメソッドが用意されており、それぞれ表示色が異なります。
状況に応じて、 info
, comment
,question
,error
なども使い分けましょう。
表示色のサンプルです。
引数
コマンドに引数を設定するには、 $signature
プロパティを次のようにします。
1 | protected$signature='hello:example {first_name} {last_name}'; |
引数を取得するには、handle()
メソッドで、次のようにします。
1 2 3 4 5 6 | publicfunctionhandle() { $firstName=$this->argument('first_name'); $lastName=$this->argument('last_name'); $this->line("$firstName $lastName"); } |
実際のコマンド実行は、次のようになります。
1 2 | $php artisan hello:example taro hoge taro hoge |
$signature
を次のようにすると、配列として引数を受け取ることができます。
1 | protected$signature='hello:example {name*}'; |
オプション
オプションを指定し、値を取得するには、 $signature
プロパティを次のようにします。
1 | protected$signature='hello:example {--firstname=} {--lastname=}'; |
オプションにデフォルト値を設定する場合は、上記の =
に続けてデフォルト値を記載します。
また、bool値の取得であれば、 =
は不要です。
オプションの値を取得するには、 handle()
ソメッドで、次のようにします。
1 2 3 4 5 6 | publicfunctionhandle() { $firstName=$this->option('firstname'); $lastName=$this->option('lastname'); $this->line("$firstName $lastName"); } |
実際のコマンド実行は次のようになります。
1 2 | $php artisan hello:example--firstname=taro--lastname=hoge taro hoge |
入力を使用した対話型
対話型のコマンドを作成することも可能です。
ask()メソッド
ユーザに入力を要求することができます。
1 2 | $name=$this->ask('名前を入力してください。'); $this->line('こんにちは'.$name.'さん'); |
実行結果は次のようになります。
1 2 3 4 5 6 | $php artisan hello:example 名前を入力してください。: >Taro こんにちはTaroさん |
secret()メソッド
ask()
と似ていますが、入力内容がコンソールに表示されません。
1 | $name=$this->secret('パスワードを入力してください。'); |
confirm()メソッド
Y/Nで確認を取りたい時に使用します。
1 2 3 4 5 6 7 | publicfunctionhandle() { if($this->confirm('これでよろしいですか?')){ // yが入力された時 $this->line('完了しました'); } } |
実行結果は次のようになります。
1 2 3 4 5 6 | $php artisan hello:example これでよろしいですか?(yes/no)[no]: >yes 完了しました |
プログレスバー
時間のかかる処理を実行するときは、プログレスバーで進捗を表示することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | publicfunctionhandle() { $bar=$this->output->createProgressBar(10); $bar->start(); for($i=0;$i<10;$i++){ sleep(1); $bar->advance();// 進捗を進める } $bar->finish(); echoPHP_EOL;// 改行 $this->info('完了しました'); } |
注意点としては、プログレスバーの後は改行されないため、 echo PHP_EOL
で改行コードを出力する必要があります。
実行結果は次のようになります。
1 2 3 | $php artisan hello:example 10/10[▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓]100% 完了しました |
テーブル
テーブルを出力できることも可能です。例えば、DBのレコードを一覧表示する時に使用できます。
1 2 3 4 5 6 | publicfunctionhandle() { $headers=['id','名前','著者']; $books=Book::all(['id','title','author'])->toArray(); $this->table($headers,$books); } |
実行結果は次のようになります。
1 2 3 4 5 6 7 | $php artisan hello:example +----+-------------+----------+ |id|名前 |著者 | +----+-------------+----------+ |1 |Laravel入門|Lara太郎| |3 |PHP入門 |PHP太郎 | +----+-------------+----------+ |
サンプル実装
「国立図書館デジタルコレクション書誌情報」をダウンロードし、テーブルに格納するコマンドのサンプルコードです。
ダウンロードにはGuzzleHttp、ExcelデータのインポートにはLaravel Excelを使用しています。
BooksImport.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <?php namespaceApp\Imports; useApp\Book; useMaatwebsite\Excel\Concerns\Importable; useMaatwebsite\Excel\Concerns\ToModel; useMaatwebsite\Excel\Concerns\WithHeadingRow; useMaatwebsite\Excel\Concerns\WithProgressBar; classBooksImport implementsToModel,WithProgressBar { useImportable; /** * @param array $row * * @return \Illuminate\Database\Eloquent\Model|null */ publicfunctionmodel(array$row) { if($row[0]==='URL'){ returnnull; } $book=newBook(); $book->title=$row[1].' '.$row[2]; $book->author=$row[5]; $book->description=$row[15]; return$book; } } |
ImportBooks.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | <?php namespaceApp\Console\Commands; useApp\Imports\BooksImport; useGuzzleHttp\Client; useIlluminate\Console\Command; useIlluminate\Support\Facades\Storage; classImportBooksextendsCommand { /** * The name and signature of the console command. * * @var string */ protected$signature='import:books'; /** * The console command description. * * @var string */ protected$description='Command description'; /** * Create a new command instance. * * @return void */ publicfunction__construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ publicfunctionhandle() { if(!$this->confirm('図書データを新規追加します。よろしいですか?')){ return; } $this->line('ダウンロードしています。'); $bar=$this->output->createProgressBar();// ダウンロードファイルサイズは後から取得するため、初期値は設定しない。 $bar->start(); $client=newClient(); $path=Storage::path('books.xlsx'); $client->request( 'GET', 'https://dl.ndl.go.jp/files/dataset/dataset_202001_t_kannai.xlsx', [ 'sink'=>$path, 'progress'=>function($downloadTotal,$downloadedBytes,$uploadTotal,$uploadedBytes)use($bar){ $bar->setMaxSteps($downloadTotal);// ダウンロードサイズ $bar->setProgress($downloadedBytes);// ダウンロード済みサイズ } ]); $bar->finish(); echoPHP_EOL; $this->info('ダウンロード完了'); $this->line('インポートしています。'); // Laravel ExcelのwithOutput()メソッドを使用すると、コンソールにプログレスを表示することができる。 (newBooksImport())->withOutput($this->output)->import($path); $this->info(' インポート完了'); } } |
$ php artisan import:books
コマンドで実行できます。
さいごに
いかがでしたか。 artisan
コマンドは、よくコンソールで使用される機能が揃っているので、ちょっとした手作業を自動化する際に、使い勝手が良さそうですね。