【Laravel】対話コマンドを作る

 対話コマンドはざっくばらんに言えば入力の受付と出力を繰り返すコマンドです。引数や分岐の多いコマンドは対話式にするとミスが減り便利です。Laravelはコンソールのデザインのための機能もリッチで想像の万倍簡単に作れるよう用意がされていました。例えば、次のスクリーンショットの対話コマンドが
 
次のコードで作れます。

<?php

namespace App\Console\Commands;

use App\Console\BaseCommand;
use Carbon\Carbon;

class HogeCommand extends BaseCommand
{
    /**
     * The name and signature of the console command.
     * @var string
     */
    protected $signature = 'hoge:add';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '対話コマンド例';

    /**
     * コンソール上での文字列強調. 実際はBaseCommand内に置いたり
     * @param  string|int|float $str
     * @return string
     */
    protected static function highlight($str): string
    {
        return '<fg=white;options=bold,underscore>'.$str.'</>';
    }
    
    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $this->info("対話コマンドを開始します。\nメッセージの右側にでる[]内の値はデフォルト値です。\n入力なしにEnterを押すとデフォルト値が入力値として扱われます。");
        $dateTime = $this->askDateTime();
        $regex    = $this->askRegex();

        $confirm = $this->confirm(
            implode(
                "\n",
                [
                    '以下の設定で入力を確定してよろしいでしょうか?よろしければ'.self::highlight('yes').'を入力してください。',
                    '日時: '.self::highlight($dateTime),
                    '文字列: '.self::highlight($regex),
                    '',
                ]
            )
        );
        if (! $confirm) {
            $this->info('入力は確定されませんでした.');
        } else {
            $this->info('入力を確定しました.');
        }
    }

    /**
     * 日時を尋ねる
     * @return Carbon
     */
    private function askDateTime(): Carbon
    {
        $valid = false;
        while (! $valid) {
            $dateTime = $this->ask('日時を入力してください。', now());
            try {
                $dateTime = new Carbon($dateTime);
                $valid    = true;
            } catch (\Exception $e) {
                $valid = false;
                $this->error('日時形式と判別できませんでした。"年-月-日 時:分:秒"などの形式で入力してください');
            }
        }

        return $dateTime;
    }

    /**
     * 正規表現に従う入力
     * @param  string $pattern 正規表現パターン
     * @return string
     */
    private function askRegex($pattern = '/\A-?\d+\z/'): string
    {
        $valid = false;
        while (! $valid) {
            $inputStr = $this->ask($pattern.'に従う文字列を入力してください。');
            $valid    = (bool) preg_match_all($pattern, $inputStr);
        }

        return $inputStr;
    }
}

 Laravel基本機能だけでも随分作りやすいです。次のリンク先の”コマンドI/O”の項目が特に重要です。
Artisanコンソール 6.x Laravel
 よく使うが手作りが辛い機能である、対話、自動補完、選択肢、表の書き出し、プログレスバーがLaravelの中に用意されています。とりあえず次のaskメソッドがあるだけでかなりそれっぽくなります。

$inputValue = $this->ask('質問文');

 もっとデザインに気を配るならば、次リンクから始まるSymfonyのConsoleに関するをドキュメントを読むと良いです。
The Console Component (Symfony Docs)
 Artisanコマンドの標準出力用メソッド($this->info()とか)では次メソッドの様なSymfonyで用意された文字修飾のタグ付けが使えます。

    /**
     * コンソール上での文字列強調. 実際はBaseCommand内に置いたり
     * @param  string|int|float $str
     * @return string
     */
    protected static function highlight($str): string
    {
        return '<fg=white;options=bold,underscore>'.$str.'</>';
    }
>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG