Artisanコマンドの自作方法とテストコード

Artisanコマンドの自作方法とテストコード

こんにちはー!むちょこです。

先日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
app/Console/Commands/Sample.php
<?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つでもいいですし

app/Console/Commands/Sample.php
protected $signature = 'sample';

:で繋ぐことで、グルーピングすることもできます。

app/Console/Commands/Sample.php
protected $signature = 'group:sample';

具体例として既存のコマンドを例に出すと、前者はphp artisan migrate、後者はphp artisan make:migrationなどがあります。

$description

app/Console/Commands/Sample.php
protected $description = 'Sampleコマンドの説明';

$descriptionには、このコマンドの説明文を代入します。

代入された値は、php artisan listで表示されるArtisanコマンド一覧に表示されます。

コマンド
$ php artisan list
php artisan listの結果

handle()

handleメソッドには、このコマンドを実行したときの処理を書きます。

基本的にはControllerなどと同じで、例えばModelを使いたいときはこんな感じに書きます。

app/Console/Commands/Sample.php
use App\User;

class Sample extends Command
{
    public function handle()
    {
        $user = User::find(1);
    }
}

引数

コマンドで引数を渡したいときは、 まず$signatureで定義します。

ここでは、例としてUserIDを引数にとってみます。

app/Console/Commands/Sample.php
protected $signature = 'sample:user {user_id}';

渡された引数は、argumentsメソッドで受け取ることができます。

app/Console/Commands/Sample.php
    public function handle()
    {
        $user_id = $this->argument('user_id');
        $user = User::find($user_id);
    }

引数は複数定義することができ、デフォルト値を指定することも可能です。

デフォルト値が1のstatusという引数を追加した例。

app/Console/Commands/Sample.php
protected $signature = 'show:user {user_id} {status=1}';

その他、 {user_id?} のように書くと引数の指定を任意にすることも可能です。

出力

コンソールに文字を出力するためにいくつかのメソッドが用意されていますが、ここではinfoメソッドを使ってみます。

app/Console/Commands/Sample.php
   public function handle()
    {
        $user_id = $this->argument('user_id');
        $user = User::find($user_id);
        $this->info($user->name);
    }
MEMO

他のメソッドも知りたい方はこちらはこちらをどうぞ!

https://readouble.com/laravel/5.7/ja/artisan.html#writing-output

完成したサンプルコード

完成したサンプルコードの全体像はこんな感じです。

app/Console/Commands/Sample.php
<?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
tests/Feature/CommandTest.php
<?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);
    }
}

最低限のテストコードはこんな感じになります。

tests/Feature/CommandTest.php
    /** @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になります。

MEMO

このほかのコンソールテストに使えるメソッドはこちらをご覧ください。

https://readouble.com/laravel/5.7/ja/console-tests.html

これで自作Artisanコマンドの完成です!?

(実際にはもっとエラー処理などが必要ですが、今回は割愛します)。