【保存版】Laravel 独自Artisanコマンド大全集!

こんにちは。フリーランス・コンサルタント&エンジニアの 九保すこひ です。

さてさて、このブログでは移転前からLaravelに関する記事をお届けしているので、すでに色々な機能を紹介してきました。

とはいえ、Laravelはホントにたくさんの機能を備えているのでまだまだ取り扱っていない話題が残っていたりします。

そして今回は、その中でも私が好きな機能「独自Artisanコマンド」の作り方をご紹介します。

ちなみに、Artisanコマンドというのは、Laravelがデフォルトで備えている機能で、例えば「マイグレーション」だったり「コントローラーの自動作成」は皆さんもよく使うかもしれません。

そして、Artisanコマンドというだけあって、実行はコマンドライン(ターミナル)で行います。

こんな感じですね。
↓↓↓

そのため、特に独自Artisanコマンドは、cronでタイマー予約を実行させる場合に便利ではないでしょうか。(例えば、アクセス回数の集計などある一定期間でプログラムを実行したい場合などですね)

ということで今回は、独自コマンドを作る方法をご紹介します!

実行環境: Laravel 5.8

独自のArtisanコマンドをつくる基本

コマンドで実行するファイルを作成する

独自のArtisanコマンドを作成するには、どうするかというと、Artisanコマンドを使います(笑)

では、ターミナルでLaravelがインストールされているフォルダまで移動し、以下のコマンドを実行してみてください。

php artisan make:command TestCommand

これでapp/Console/TestCommand.phpというコマンドの実行ファイルが作成されます。(ただし、まだ実際には独自コマンド実行はできません)

では、このファイルを使って以下のコマンドを実行すると「Hello!^^」と表示するようにしてみましょう。

php artisan hello

TestCommand.phpの変更後のコードはこうなります。

<?php

// 省略

class TestCommand extends Command
{
    protected $signature = 'hello';
    protected $description = 'Hello と表示する';

    // 省略
    public function handle()
    {
        echo "Hello!^^";
    }

まず$signatureの部分。これはコマンドのphp artisan ..に続く部分になりますので今回は「hello」です。

また、$descriptionはそのコマンドの説明文で、php artisan hello --helpを実行したときに表示されることになります。(あまりこういう場合は日本語の全角文字は使うべきではありませんがわかりやすく説明するためにあえて使いました。なお、私の環境ではマルチバイト文字もうまく表示できました)

そして最後にhandle()内に「Hello!^^」を表示する部分を作っています

作成したコマンドファイルをLaravelに登録する

さきほどの項目で「まだ実際にはコマンド実行はできません」と書いたのはまだLaravelにコマンドとして登録されていないからです。

ただ、登録の方法は簡単でapp/Console/Kernel.php内にある$commandsに以下のようにクラスを登録するだけです。

use App\Console\Commands\TestCommand;

class Kernel extends ConsoleKernel
{
    protected $commands = [
        TestCommand::class
    ];

実際にArtisanコマンドを実行してみる

では、実際にコマンドを実行してみましょう。
↓↓↓

はい!
うまく表示されました。

これで独自Artisanコマンドを作る方法は終了です。

もっとシンプルにコマンドを作りたい

ここまでで紹介した方法は独自Artisanコマンドを作るノーマルな方法になります。ただ、ほしい機能によっては「そこまで複雑じゃなくていいんだけどなー」なんて場合もあるかと思います。

実はLaravelにはそんな「ちょっとしたコマンド」を作成する方法も提供されています。

では、サンプルとしてコマンドを実行すると「Aloha!」と表示するだけのシンプルな独自コマンドを作ってみましょう。

まずは、routes/console.phpというファイルを開いて以下のようなコマンドを追加しましょう。

Artisan::command('aloha', function () {

    $this->info('Aloha!');

})->describe('Aloha を表示する');

やっていることは、

  • function()内で実行したいコードを書く ・・・ つまり前項目のhandle()ですね。
  • describe()で説明文を指定する ・・・ これはなくても問題ありません。また、わかりやすく説明するために日本語を使っていますが、実際には半角英数字の方がいいでしょう。

の2つです。

もちろん以下のように変数やオプションも使えます。

Artisan::command('aloha {name}', function () {

    $this->info('Aloha!');

});

独自Artisanコマンドに変数やオプション値をつける

例えば、独自Artisanコマンドに以下のような可変のデータを追加したい場合です。

php artisan hello John --from=Mike

このようにすることで、状況に応じたコマンドの実行ができるようになります。ではひとつずつ見ていきましょう。

変数をつける

基本的な変数

例えば、以下のようにHelloに続く名前を(必須)入力とするコマンドを作ってみましょう。

php artisan hello xxx

TestCommand.phpの例で言うと、以下のように変数を波括弧で囲みます。

protected $signature = 'hello {name}';

そして、この{name}のデータを取得するにはargument()メソッドを使いましょう。

$name = $this->argument('name');

ただし、この状態では先ほども書いたとおり変数は必須入力であることに注意してください。つまり、この状態で変数を省略しようとするとエラーが発生することになります。

実際のエラーです。(超意訳:「nameっていう変数がねーよ??」)
↓↓↓

そのため、もし省略もOKにしたい場合は以下のように?マークをつけます。

protected $signature = 'hello {name?}';

さらに、もし省略された場合にデフォルト値を使いたい場合は以下のように=をつけるといいでしょう。

protected $signature = 'hello {name=Michael}';

なお、もし複数の変数を使いたい場合は以下のようにいくつでも追加することができます。

protected $signature = 'hello {name=Michael} {smile=^o^}';

変数に配列を指定する

例えば、以下のように複数の名前を変数として指定する場合です。

php artisan hello John Bob Peter

変数に配列を指定するには以下のように*を最後につけます。

protected $signature = 'hello {from*}';

取得方法は、基本的な変数と同じく$this->argument('***')を使います。

オプションをつける

true / false を取得するオプション

例えば、表示をする/しないを決める--displayオプションをつけたい場合です。

protected $signature = 'hello {--display}';

この場合、以下のようにオプション値を取得することでテキストの表示/非表示を切り替えることができます。

// php artisan hello --display を実行

public function handle()
{
    $display = $this->option('display'); // この場合は、true になる

    if($display) {

        echo "Hello!\n"; // 表示される

    }
}

値を取得するオプション

例えば、以下のコマンドを実行すると「Hello, Bob!」と入力した名前を表示したい場合です。

php artisan hello --from=Bob

この場合は先ほどのtrue / falseの場合と違い、=をつける必要があります。なお、もちろんイコールの後にはデフォルト値を指定することもできます。

protected $signature = 'hello {--from=}';

// デフォルト値を指定する場合・・・

protected $signature = 'hello {--from=Bob}';

これで、option()メソッドを使って値を取り出すことができます。

$from = $this->option('from'); // Bob や Peter が入ってくる

ちなみにコマンドに詳しい方ならご存知でしょうが、オプションの指定方法にはショートカット・バージョンもあります。Laravelではこのショートカット版のオプション指定にも対応しています。

例えば、次のように-Fを使ってfromの値を入力したい場合です。

php artisan hello -F Bill

この場合、コマンドのフォーマットは次のようになります。

protected $signature = 'hello {--F|from=Bill}';

もちろん、デフォルト値の指定方法は同じですし、--from=xxxも使えます。

配列を取得するオプション

例えば、以下のように--fromで複数の名前を指定したい場合です。

php artisan hello --from=John --from=Bob --from=Peter

この場合は、変数と同じように*をつけます。

protected $signature = 'hello {--from=*}';

なお、データを取得するのは通常と同じく$this->option('***')を使います。

一気に変数やオプションを取得する

変数やオプションをたくさん指定するといちいち$this->argument('***')$this->option('***')などと書くのはめんどうになったりもするでしょう。

そんな場合は以下2つのメソッドを使うと一気に配列で値を取得することができます。

// 変数の場合
$arguments = $this->arguments();

// オプション
$options = $this->options();

※ もし変数やオプションが存在しない場合はnullが格納されます。

変数、オプションに説明文をつける

変数やオプションは便利ですが、全ての意味を覚えておくのは簡単ではありません。そのため、そんな場合に備えて変数やオプションに説明文をつけることができます。

オプションを使って実際の方法をみてみましょう。

protected $signature = 'hello {--name=Bob : あいさつする人の名前}';

このように説明文をつけるには:を使います。

※ 注意: わかりやすく説明するために使っていますが、日本語は使わない方が無難です。

php artisan hello --helpを実行すると以下のようになります。

変数の場合はこうなります。

アウトプットする

テキストをアウトプットする

例えば、処理が終了した場合などに「Done!」などとしてテキストを表示したい場合には以下5つのアウトプット方法を使うことができます。

  • line() ・・・ 装飾なしのテキスト
  • info() ・・・ 緑テキスト
  • question() ・・・ 青のテキスト
  • comment() ・・・ 黄色のテキスト
  • error() ・・・ 赤のテキスト

※ 色はUbuntu 18.04のターミナルで実行したものですが、通常は同じような色になるかと思います。

実際の使い方は以下のようになります。

public function handle()
{
    $this->line('line');
    $this->info('info');
    $this->question('question');
    $this->comment('comment');
    $this->error('error');
}

実行したもの
↓↓↓

ちなみに自動的に改行してくれるので\nなどの改行コードを最後につける必要はありません。

テーブルでアウトプットする

たくさんのデータをアウトプットしたい場合はテーブル上にしてアウトプットができるtable()を使うといいでしょう。

使い方はこうなります。

$headers = ['Name', 'Age'];
$students = [
    ['鈴木', 26],
    ['佐藤', 32],
    ['田中', 21],
];
$this->table($headers, $students);

実行結果はこうなります。

プログレスバーを表示する

プログレスバーというのは、「今どのくらい処理が完了しているかが分かる表示」です。例えば、外部ストレージにファイルをアップロードする場合は時間がかかる場合が多いですが、こういった場合にプログレスバーを表示しておくと状況をリアルタイムで把握できるのでとても便利です。

実際のコードです。
内容としては、10件のデータで時間がかかる処理をするというものになります。

$count = 10;
$progress = $this->output->createProgressBar($count);
$progress->start();

for($i = 0 ; $i < $count ; $i++) {

    // ここで時間がかかる処理

    $progress->advance(); // 次に進む
    sleep(1); // テストでつけていますが本来はいりません。

}

$progress->finish();

実行結果です。

入力をする

例えば、独自コマンドを実行し、対話形式で名前やEmailなどを入力させたい場合に使う機能です。

通常の入力

例えば、名前を入力してもらいたい場合はask()を使います。

$name = $this->ask('お名前は?');
$this->line($name .'さん、こんにちは!');

実際に実行すると以下のようになります。

なお、第2引数でデフォルト値を指定することができ、その場合は以下のようになります。

秘密の入力

例えば、パスワードなど入力したものを表示させたくない場合はsecret()を使います。

$password = $this->secret('パスワードは?');
$this->line('パスワードは、「'. $password .'」です。');

Yes / No の確認

Yes / No の確認をしたい場合は、confirm()を使います。

if($this->confirm('ポテトも付けますか?')) {

    $this->line('ポテトつけます!');

}

実際に実行するとこうなります。

なお、デフォルト値を指定していない場合はfalseになりますが、第2引数で指定することもできます。

$this->confirm('ポテトも付けますか?', true);

選択肢の中から選ばせる

いくつかの選択肢の中から選ばせる場合は、choice()を使います。

$default_index = 0;
$lunch = $this->choice('今日のランチは?', ['カフェ', '牛丼', 'Uber eats'], $default_index);
$this->line($lunch .'にしよう!');

実際に実行するとこうなります。

ちなみに、choice()は用意された選択肢にないものを選ぶとエラーが発生します。

※ もし選択肢以外のものも入力させたい場合は、anticipate()を使ってください。

候補が用意された入力

あらかじめいくつかの選択肢を用意しておくけれど、自由な入力も許可したい場合は、anticipate()を使います。

$dinner = $this->anticipate('今日のディナーは?', ['和食', '洋食', '中華']);
$this->line($dinner .'にしよう!');

実際に実行するとこうなります。

一見すると通常の入力と同じように見えますが、キーボードの上/下で候補を選択することができます。

もちろん自由に入力することもできます。

なお、第2引数でデフォルト値を指定することもできます。
実際に実行したものはこちら。

おまけ:cronで実行できない場合は・・・

独自のArtisanコマンドを作ってcronでタイマー実行しようとする場合以下のようにしてもうまくいかない場合があります。

30 12 * * * php artisan hello

この原因のひとつとして、パスがうまく指定できていないことが挙げられます。そのため、もしうまく実行できない場合は以下のようにフルパスで指定をしてみるといいでしょう。

30 12 * * * /usr/bin/php /var/www/html/laravel58/artisan hello

ちなみにPHPのフルパスを取得するには以下のコマンドを実行します。

which php
開発のご依頼お待ちしております
開発のご依頼はこちらから: お問い合わせ
どうぞよろしくお願いいたします! by 九保すこひ

おわりに

ということで、今回は独自のArtisanコマンドを作成する方法をお届けしました。簡単なサイトだけでしたらコマンドを使わずともある程度の機能をつくることはできると思いますが、例えば大きなファイルをアップロードしたり、Pythonなどの他の言語と連携する必要がある場合はコマンドがどうしても必要になってきたりします。

ぜひ皆さんもこのページを使って楽に独自コマンドを作って連携させてみてくださいね。

ではでは〜!(久しぶりの長文記事でちょっと疲れました ^^;)

「おやすみなさい…」

このエントリーをはてなブックマークに追加       follow us in feedly