【Laravel】Artisanコマンドの作成方法

[qnote Advent Calendar 2022](https://qiita.com/advent-calendar/2022/qnote) の19日目の記事です。

# はじめに
いつも使っているArtisanコマンドですが、業務で自作する機会がありました。
少し気になったので備忘録がてら書きました🐱

## 環境
PHP 8.0.25
Laravel 9.34

# コマンド作成
```shell
$ php artisan make:command SampleCommand
```

```PHP:SampleCommand.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class SampleCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:sample';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'サンプルコマンド';

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $this->comment('hello class command');
    }
}
```

- `$signature`
コマンド名を指定
- `$description`
コマンドの説明を指定
- `handleメソッド`
実行する処理を記述

# 確認
`php artisan list`で作成したコマンドとdescriptionを確認することができます。
```shell
$ php artisan list
Laravel Framework 9.34.0

Usage:
  command [options] [arguments]

Options:
  -h, --help            Display help for the given command. When no command is given display help for the list command
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi|--no-ansi  Force (or disable --no-ansi) ANSI output
  -n, --no-interaction  Do not ask any interactive question
      --env[=ENV]       The environment the command should run under
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

command
  command:sample                                サンプルコマンド
```

# 実行
```shell
$ php artisan command:sample
=> hello class command
```

# コマンド引数の指定
コマンド引数は、`$signature`プロパティにコマンド名とともに指定し、引数名を`{}`で囲います。
```php:SampleCommand.php
protected $signature = 'command:sample {name}';
```

## コマンド引数の取得
```php:SampleCommand.php
public function handle()
{
    $name = $this->argument('name');
    $this->comment($name);
    return 0;
}
```

引数を省略してコマンドを実行するとエラーになります。
```shell
$ php artisan command:sample
=> Not enough arguments (missing: "name").
```

### コマンド引数の指定方法
|  コマンド引数  |  内容  |
| ---- | ---- |
|  `{name}`  |  引数を文字列として取得。省略するとエラー  |
|  `{name?}`  |  引数を文字列として取得。省略可能  |
|  `{name=hoge}`  |  引数を文字列として取得。省略すると=の右辺がデフォルト値となる。  |
|  `{name*}`  |  引数を配列として取得。省略するとエラー  |

ちなみに`{name*}`の場合、引数の順番に配列として渡されます。
- 値が1つの場合
`php artisan command:sample hoge`
```shell
array:1 [
  0 => "hoge"
]
```

- 値が2つ以上の場合
`php artisan command:sample hoge huga`
```shell
array:2 [
  0 => "hoge"
  1 => "huga"
]
```

# オプション引数の指定
コマンド引数と同様に、`$signature`プロパティに指定します。
`{}`で囲み、先頭に`--`を指定するとオプション引数となります。
```php:SampleCommand.php
protected $signature = 'command:sample {--name}';
```

## オプション引数の取得
```php:SampleCommand.php
public function handle()
{
    $name = $this->option('name');
    $this->comment($name);
    return 0;
}
```

### オプション引数の指定方法
|  コマンド引数  |  内容  |
| ------ | ------ |
|  `{--name}`  |  引数をBooleanとして取得。指定するとtrue、省略するとfalseとなる。  |
|  `{--name=}`  |  引数を文字列として取得。省略可能  |
|  `{--name=hoge}`  |  引数を文字列として取得。省略すると=の右辺がデフォルト値となる。  |
|  `{--name=*}`  |  引数を配列として取得。`--name=hoge`、`--name=huga`と指定すると、`['hoge', 'huga']`といった配列になる。  |

コマンド引数と違い、こちらはオプションなので省略してもエラーになりません。

# 結果の出力
主な出力用メソッド
|  メソッド  |  出力スタイル  |
| ---- | ---- |
|  `line($string, $style=null, $verbosity=null)`  |  スタイルなし  |
|  `info($string, $verbosity=null)`  |  infoスタイル (文字色:緑)  |
|  `comment($string, $verbosity=null)`  |  commentスタイル (文字色:黄)  |
|  `question($string, $verbosity=null)`  |  questionスタイル (文字色:黒、背景色:シアン)  |
|  `error($string, $verbosity=null)`  |  errorスタイル (文字色:白、背景色:赤)  |
|  `warn($string, $verbosity=null)`  |  warnスタイル (文字色:黄)  |

全て見たことある色ですね。。。
![スクリーンショット 2022-12-19 0.03.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/752214/9cb866a8-d762-a73e-c8ff-b7807bf1665e.png)

# 出力レベルの設定
出力用メソッドの引数に、`OutputInterface`クラスの定数を置いてあげると、レベル別に表示分けすることができます。
```php:SampleCommand.php
$this->comment($name, OutputInterface::VERBOSITY_NORMAL);
```

## レベル表
|  名前  |  定数値  |  出力レベル  |
| ---- | ---- | ---- |
|  `VERBOSITY_QUIET`  |  16  |  常に出力  |
|  `VERBOSITY_NORMAL`  |  32  |  デフォルトの出力レベル。  |
|  `VERBOSITY_VERBOSE`  |  64  |  -v、-vv、-vvvで出力  |
|  `VERBOSITY_VERY_VERBOSE`  |  128  |  -vv、-vvvで出力  |
|  `VERBOSITY_DEBUG`  |  256  |  -vvvでのみ出力  |

# まとめ
引数周りは漠然としていたので、理解を深めることができました。
スケジューラと組み合わせてバッチ処理を作成することもできるので、状況に応じて使い分けていきましょう。
![スクリーンショット 2022-12-19 1.15.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/752214/3002c638-2e4a-57c5-33c1-fde274b2cfc6.png)