こんにちはー!むちょこです。
先日Arisanコマンドを自作していたのですが、公式ドキュメントだけだとちょっと分かりづらそう&ざっと調べた感じだとあまり情報がなかったので記事にしようと思います☆
Artisanコマンドとは
ArtisanはLaravelに含まれているコマンドラインインターフェイスです。
https://readouble.com/laravel/5.7/ja/artisan.html
Laravelで開発するときはよく、「php artisan migrate」とか叩いてますよね。これがArtisanコマンドです。
ご存知の方もいるかと思いますが、実はこれ、簡単に自作できます?
環境
今回の動作確認は、Laravel Framework 5.7.24上で行いました。
Artisanコマンドの自作は5.1以降から、コンソールテストは5.7以降から対応しています。
Artisanコマンドの自作方法
まずは、Commandクラスの雛形を生成します。
$ php artisan make:console Sample
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class Sample extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'command:name';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
//
}
}
$signature
$signatureには、「php artisan xxx」のxxxにあたる任意のコマンド名を代入します。
シンプルに1つでもいいですし
protected $signature = 'sample';
:で繋ぐことで、グルーピングすることもできます。
protected $signature = 'group:sample';
具体例として既存のコマンドを例に出すと、前者はphp artisan migrate、後者はphp artisan make:migrationなどがあります。
$description
protected $description = 'Sampleコマンドの説明';
$descriptionには、このコマンドの説明文を代入します。
代入された値は、php artisan listで表示されるArtisanコマンド一覧に表示されます。
$ php artisan list
handle()
handleメソッドには、このコマンドを実行したときの処理を書きます。
基本的にはControllerなどと同じで、例えばModelを使いたいときはこんな感じに書きます。
use App\User;
class Sample extends Command
{
public function handle()
{
$user = User::find(1);
}
}
引数
コマンドで引数を渡したいときは、 まず$signatureで定義します。
ここでは、例としてUserIDを引数にとってみます。
protected $signature = 'sample:user {user_id}';
渡された引数は、argumentsメソッドで受け取ることができます。
public function handle()
{
$user_id = $this->argument('user_id');
$user = User::find($user_id);
}
引数は複数定義することができ、デフォルト値を指定することも可能です。
デフォルト値が1のstatusという引数を追加した例。
protected $signature = 'show:user {user_id} {status=1}';
その他、 {user_id?} のように書くと引数の指定を任意にすることも可能です。
出力
コンソールに文字を出力するためにいくつかのメソッドが用意されていますが、ここではinfoメソッドを使ってみます。
public function handle()
{
$user_id = $this->argument('user_id');
$user = User::find($user_id);
$this->info($user->name);
}
完成したサンプルコード
完成したサンプルコードの全体像はこんな感じです。
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\User;
class Sample extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'sample:user {user_id}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Sampleコマンドの説明';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$user_id = $this->argument('user_id');
$user = User::find($user_id);
$this->info($user->name);
}
}
渡されたUserIDのユーザ名を表示するというシンプルなコマンドができました。
テストコード
先ほど作ったコマンドのテストを書いていきます。
まずは雛形の生成です。
$ php artisan make:test CommandTest
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class CommandTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testExample()
{
$this->assertTrue(true);
}
}
最低限のテストコードはこんな感じになります。
/** @test */
public function show_user()
{
$user = factory(\App\Models\User::class)->create();
$this->artisan('sample:user', [
'user_id' => $user->id
])->expectsOutput($user->name);
}
artisanメソッド
$this->artisan('sample:user', [
'user_id' => $user->id
])
Artisanコマンドを実行することができます。
第一引数に実行したいコマンド、第二引数にはコマンドの引数を入れます。
コマンドの引数は連想配列にする必要があることにご注意ください☆
expectsOutputメソッド
->expectsOutput($user->name);
コマンドを実行した後に出力される値が引数と一致するとtrueになります。
これで自作Artisanコマンドの完成です!?
(実際にはもっとエラー処理などが必要ですが、今回は割愛します)。