Laravelでartisanコマンドを自作してCommandを体感する

Laravelを勉強してて、php artisan という不思議なコマンドを何気なく使っていましたが
これを自作できるということで、自作した勉強メモです。


## artisanコマンド一覧を見てみる

まずはどんなコマンドがあるのか見てみることにしました。

```
php artisan list
```

このコマンドを使うことで、どんなコマンドが使えるのか、またそのコマンドの説明が表示されます。

```
Laravel Framework 6.0.4

Usage:
  command [options] [arguments]

...

make
  make:channel         Create a new channel class
  make:command         Create a new Artisan command
  make:controller      Create a new controller class
  make:event           Create a new event class
  make:exception       Create a new custom exception class
  make:factory         Create a new model factory
  make:job             Create a new job class
  make:listener        Create a new event listener class
  make:mail            Create a new email class
  make:middleware      Create a new middleware class
  make:migration       Create a new migration file
  make:model           Create a new Eloquent model class

...

```

ズラーと表示されました。中には馴染みのあるmake:migrationなんかもあります。
Create a new migration fileと書いてあるので、コマンドの簡単な説明も一緒に表示されていることがわかります。


この中に

```
make:command         Create a new Artisan command
```

というのがあるので、これを使ってコマンドを作ります。

```
php artisan make:command SampleCommand

Console command created successfully.
```

これで
app/Console/Commands/SampleCommand.php
というファイルが作成されました。
ここにどんなコマンドなのか具体的に記載していきます。

コマンドの名前の指定や、説明、handleメソッドにコンストラクタがあります。


## どんなコマンドにするか考える

せっかくなので何かできるコマンドにしたかったので
テーブルのレコードをアップデートするコマンドにしました。

jsonファイルを読み込ませて
その内容に従ってテーブルのレコードをアップデートします。
アップデートが終わったらjsonファイルをDoneフォルダに移動させます。

まぁ、実用性はないですが、、、。。。

```
{
	"table": "customers",
	"where": "id",
	"conditions":"1",
	"update": "name",
	"value":"高田健志"
}
```


## コマンドファイルを編集する

まずは名前を変更します。

```php:SampleCommand.php
//protected $signature = 'command:name';
protected $signature = 'myupdate:table {filename}';
```

これがartisanコマンドになります。
使うときは

```
php artisan myupdate:table Sample.json
```

というようになります。
{arg}で引数を指定することもできます。

次にコマンドの説明を変更します。

```php:SampleCommand.php
//protected $description = 'Command description';
protected $description = 'update table';
```

この状態でもう一回listを表示してみます。

```
 myupdate
  myupdate:table       update table
```

登録したコマンド名と説明が表示されています。
あとはコマンドの処理を実装するだけです。

コマンドの処理の中身はhandleメソッドに書いていきます。


```php:SampleCommand.php

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {

        //引数のファイル名を取得する
        $filename = $this->argument('filename');

        //infoは緑色の文字でメッセージを表示する
        $this->info("start update table command!");

        //引数のファイルがなければ処理を終わりにする
        if( !file_exists(base_path('MyUpdate/'.$filename)) ){
            dd("ファイルが無いお（；＿；）");
        }

        // jsonファイルを解析する
        $json_data = file_get_contents(base_path('MyUpdate/'.$filename));
        $result = json_decode($json_data);

        $this->info("before...");

        //jsonのデータでテーブルからレコードを取得する。
        $target = \DB::table($result->table)
        ->where($result->where,$result->conditions)
        ->first();

        //取得したレコードを表示する
        var_dump($target);


        // jsonのデータでテーブルのレコードを更新する
        $query = \DB::table($result->table)
            ->where($result->where,$result->conditions)
            ->update([
                $result->update => $result->value
            ]);
        
        $this->info("after...");
        

        $target = \DB::table($result->table)
            ->where($result->where,$result->conditions)
            ->first();
    
        var_dump($target);
        

        // 終えたらファイルを移動する
        // もしDoneフォルダがなければ作成する
        if( !file_exists(base_path('MyUpdate/Done')) ){
            mkdir(base_path('MyUpdate/Done'));
        }

        // jsonファイルを移動する
        rename(base_path('MyUpdate/'.$filename),base_path('MyUpdate/Done/'.$filename));

        $this->info("end update table command!");

    }
```

jsonの中身でテーブルを指定して
レコードの取得と更新を行います。

処理が終わったらjsonファイルを移動させます。


base_pathメソッドは、プロジェクトルートの完全パスを返してくれる、ヘルパ関数です。
https://readouble.com/laravel/5.5/ja/helpers.html#method-base-path

このコマンドには穴がありますが、その辺は置いといて実行したいと思います。
MyUpdateフォルダをプロジェクトルートに作成して
先ほどの中身と同じSample.jsonを作成します。


作成したコマンドを実行します。

```
php artisan myupdate:table Sample.json
start update table command!
before...
object(stdClass)#681 (4) {
  ["id"]=>
  int(1)
  ["name"]=>
  string(9) "横山緑"
  ["created_at"]=>
  string(19) "2019-10-15 10:07:53"
  ["updated_at"]=>
  string(19) "2019-10-15 10:07:53"
}
after...
object(stdClass)#684 (4) {
  ["id"]=>
  int(1)
  ["name"]=>
  string(12) "高田健志"
  ["created_at"]=>
  string(19) "2019-10-15 10:07:53"
  ["updated_at"]=>
  string(19) "2019-10-15 10:07:53"
}
end update table command!
```

コマンドを打つことで
jsonファイルを読み取って、レコードを検索して更新して、フォルダの作成とファイルの移動をする。という
なんとなーくコマンドっぽいのができました。