Laravel 5.1 中創建自定義 Artisan 控制檯命令實例教程

1、入門

Laravel通過Artisan提供了強大的控制檯命令來處理非瀏覽器業務邏輯。要查看Laravel中所有的Artisan命令,可以通過在項目根目錄運行:

php artisan list

對應輸出如下(部分截圖):

其中一些命名我們已經比較熟悉了,比如創建遷移make:migration以及執行遷移migrate,又比如創建模型make:model,創建控制器make:controller等。

如果要查看具體某個命令的使用方法,比如我們要查看創建Artisan命令make:console的具體用法,可以使用如下命令:

php artisan help make:console

對應輸出如下:

2、創建命令

Artisan除了提供豐富的控制檯命令之外,還允許我們通過make:console命令創建自己的控制檯命令。上面我們已經使用help指令查看了make:console的用法,下面我們就沿着這條路走下去,一探究竟:創建命令並運行起來得到我們想要的各種結果。

首先我們創建一個最簡單的命令,打印Hello LaravelAcademy,使用Artisan命令如下:

php artisan make:console HelloLaravelAcademy --command=laravel:academy

其中HelloLaravelAcademy是命令名,laravel:academy是控制檯執行的命令,類似make:console

執行完成後,會在app/Console/Commands目錄下生成一個HelloLaravelAcademy.php文件:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

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

    /**
     * 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即爲在控制檯執行的命令名,$description爲命令描述,handle方法爲執行命令時調用的方法。

接下來我們簡單編寫handle方法如下:

public function handle()
{
    echo "Hello LaravelAcademy\n";
}

好了,一個最簡單的命令已經編寫好了,接下來要怎麼執行並在控制檯打印出“Hello LaravelAcademy”呢?

3、運行命令

在運行命令前需要將其註冊到App\Console\Kernel$commands屬性中:

protected $commands = [
     ...  //其他命令類
     \App\Console\Commands\HelloLaravelAcademy::class
];

接下來我們就可以在控制檯運行如下Artisan命令:

php artisan laravel:academy

終端就會打印出:

Hello LaravelAcademy

是不是很簡單?

4、更多樣的輸入輸出

當然,上面是最簡單的情形,沒有輸入,寫死的輸出。實際環境中有更復雜的需求,有更多樣的輸入輸出,下面我們來一一討論。

定義輸入

上面已經提到,我們可以通過修改$signature屬性定義輸入參數及選項,比如這裏我們將上述Hello後面的字符串調整爲通過輸入參數來控制,可修改$signature如下:

protected $signature = 'laravel:academy {name}';

這樣定義意味着name是必選參數,當然還支持更多自定義參數輸入:

{name?} //可選參數
{name=LaravelAcademy} //默認name值爲LaravelAcademy

爲增強程序健壯性,我們將name修改爲有默認值:

protected $signature = 'laravel:academy {name=LaravelAcademy}';

有時候我們還會在執行命令時傳入一些選項,比如是否顯示標點符號(雖然聽上去很雞肋,這裏權當測試之用), 那麼我們可以修改$signature屬性如下:

protected $signature = 'laravel:academy {name=LaravelAcademy} {--mark}';

如果調用命令時傳遞--mark則代表其值爲true,否則爲false,如果選項值在輸入時通過用戶設置,可定義$signature如下:

protected $signature = 'laravel:academy {name=LaravelAcademy} {--mark=}';

這樣用戶就可以在傳入選項時通過=來爲選項賦值,當然和參數一樣,我們也可以爲選項指定默認值:

protected $signature = 'laravel:academy {name=LaravelAcademy} {--mark=!}';

獲取輸入

定義好輸入參數和選項後,又該如何獲取其對應值呢?Laravel爲我們提供了相應的方法。

獲取參數值可以通過Illuminate\Console\Commandargument方法:

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

如果無參調用argument方法,則返回的是所有參數值數組。

獲取選項值可以通過Illuminate\Console\Commandoption方法:

$mark = $this->option('mark');

同理,無參調用option方法會返回所有選項值數組。

這樣我們可以修改HelloLaravelAcademyhandle方法如下:

public function handle()
{
    $name = $this->argument('name');
    $mark = $this->option('mark');

    $string = 'Hello '.$name;
    if($mark)
        $string .= $mark;

    echo $string."\n";
}

這樣我們在控制檯輸入如下Artisan命令:

php artisan laravel:academy

對應輸出爲:

Hello LaravelAcademy!

再運行如下Artisan命令:

php artisan laravel:academy Laravel --mark=?

對應輸出爲:

Hello Laravel?

輸入提示

我們甚至還可以完全讓用戶通過在控制檯輸入name來獲取輸入參數,首先修改handle方法如下:

public function handle()
{
    $name = $this->ask('What do you want to say Hello?');
    echo "Hello ".$name."\n";
}

然後在終端輸入php artisan laravel:academy,交互頁面如下:

如果是輸入密碼一類的敏感信息可以用secret替代ask方法。

有時候我們會根據用戶的意願選擇繼續還是中止:

public function handle()
{
    if($this->confirm('Do you want to continue?[y|n]')){
        $this->info("Continue");
    }else{
        $this->error("Interrupt");
    }
}

對應輸出爲:

除了讓用戶手動輸入外,還可以使用anticipate方法實現自動完成功能:

public function handle()
{
    $name = $this->anticipate('What is your name?', ['Laravel', 'Academy']);
    $this->info($name);
}

當然還可以使用choice方法爲用戶提供選擇避免手動輸入,用戶只需選擇對應索引即可:

public function handle()
{
    $name = $this->choice('What is your name?', ['Laravel', 'Academy']);
    $this->info($name);
}

對應交互頁面如下:

編寫輸出

關於輸出字符串,上面我們簡單使用了echo語句,其實Laravel提供了更爲強大和多樣化的方法:

public function handle()
{
    $this->info("Successful!");
    $this->error("Something Error!");
    $this->question("What do you want to do?");
    $this->comment("Just Comment it!");
}

執行php artisan laravel:academy對應輸出如下:

表格

Artisan甚至可以輸出表格:

public function handle()
{
    $headers = ['Name', 'Email'];
    $users = \App\User::all(['name', 'email'])->toArray();
    $this->table($headers, $users);
}

執行php artisan laravel:academy對應輸出爲:

進度條

當然對於複雜耗時的命令,進度條是必不可少的,

public function handle()
{
    $this->output->progressStart(10);

    for ($i = 0; $i < 10; $i++) {
        sleep(1);
        $this->output->progressAdvance();
    }

    $this->output->progressFinish();
}

執行php artisan laravel:academy對應輸出爲:

5、從CLI之外調用Artisan

除了在控制檯執行Artisan命令之外,還可以通過代碼在別處調用Artisan命令,比如其它Artisan命令、控制器、路由或其他。

路由

在路由閉包中我們可以通過Artisan門面的call方法來調用本節創建的命令:

//在路由中調用Artisan命令
Route::get('testArtisan',function(){
    $exitCode = Artisan::call('laravel:academy', [
        'name' => 'Laravel學院', '--mark' => '!'
    ]);
});

其它Artisan命令

在一個Artisan命令中也可以調用另一個Artisan命令,還是通過call方法:

public function handle()
{
    $this->call('inspire');
}

如果想要調用一個Artisan命令並阻止其所有輸出,可以使用callSilent方法:

public function handle()
{
    $this->callSilent('inspire');
}

號外:除此之外,關於Artisan命令你還應該知道的是我們可以在創建的命令類的控制器或方法中注入任何依賴。這就意味着我們可以在命令類中使用註冊到服務容器的所有類。


學習之餘。休閒娛樂一下,爆笑一課吧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章