自定義 Artisan 命令

cangsongbayu發表於2020-01-08

執行下面的命令會生成 app/Console/Commands/{YourCommandName}.php 檔案

php artisan make:command YourCommandName

Artisan 命令類的預設架構如下

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class YourCommandName extends Command
{
    /**
     * The name and signature of the console command.
     * 這個屬性的值是命令的名稱 ,比如現在是 command:name ,那麼呼叫命令的格式就是 php artisan command:name
     *
     * @var string
     */
    protected $signature = 'command:name';

    /**
     * The console command description.
     * 這個屬性是命令的描述資訊 ,使用 php artisan help command:name 檢視命令幫助資訊時 ,會顯示這個值
     * 
     * @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()
    {
        // 現在執行這個命令就會寫一個 /test artisan 的檔案 ,內容是 test
        file_put_contents('/test artisan', 'test');
    }
}

想要使用上面建立的命令 ,還需要註冊這個命令 ,有兩種方式

2.1 app/Console/Kernel.php

在 app/Console/Kernel.php 的 $commands 屬性下新增剛剛建立的命令即可

/**
 * The Artisan commands provided by your application.
 *
 * @var array
 */
protected $commands = [
    //
    \App\Console\Commands\YourCommandName::class
];

然後就可以執行這個命令了

php artisan command:name

2.2 基於閉包的命令

// routes/console.php
Artisan::command('password:reset {userId} {--sendEmail}', function(){
    // 第一個引數是命令的名稱
    // 執行一些操作 ,比如重置使用者密碼 ...
})

以下面這個名稱為例 ,來講解 Artisan 命令的語法

protected $signature = 'password:reset {userId} {--sendEmail}';

3.1 引數

格式 說明
password:reset {userId} 用大括號將必須的引數包起來
password:reset {userId?} 可選引數加個問號
password:reset {userId=1} 預設值引數

3.2 選項

選項和引數類似 ,但是要加字首 -- ,並且也可以不賦值

格式 說明
password:reset {userId} {--sendEmail} 普通選項
password:reset {userId} {--password=} 多一個 "=" 號 ,可以為選項賦值
password:reset {userId} {--queue=default} 預設值選項

3.3 引數陣列和選項陣列

引數和選項中如果要使用陣列加一個 "*" 號

格式 說明
password:reset {userIds*} 引數陣列
password:reset {--ids=*} 選項陣列

Artisan 命令中使用陣列

# 引數
php artisan password:reset 1 2 3
# 選項
php artisan password:reset --ids=1 --ids=2 --ids=3
// 前面提到過 $description 是命令的描述資訊
protected $description = 'Command description';

還需要一些引數和選項的描述資訊

protected $signature = 'password:reset {userId : 使用者的 ID} {--sendEmail : 是否向使用者傳送郵件 1=傳送 0=不傳送}';

使用 artisan help 來檢視這個命令的幫助資訊

php artisan help password:reset
Description:
  Command description

Usage:
  password:reset [options] [--] <userId>

Arguments:
  userId                使用者的 ID

Options:
      --sendEmail       是否向使用者傳送郵件 1=傳送 0=不傳送
  -h, --help            Display this help message
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi            Force ANSI output
      --no-ansi         Disable 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

5.1 argument()

/**
 * Execute the console command.
 * 這個函式是呼叫命令時執行的操作
 *
 * @return mixed
 */
public function handle()
{
    // 定義 :password:reset {userId}
    // 執行 :php artisan password:reset 5

    $this->argument(); // 返回一個包含所有引數的陣列( 第一個元素是命令名稱 )
    // [
    //     "command" => "password:reset",
    //     "userId" => "5"
    // ]

    $this->argument('userId');
    // "5"
}

5.2 option()

/**
 * Execute the console command.
 * 這個函式是呼叫命令時執行的操作
 *
 * @return mixed
 */
public function handle()
{
    // 定義 :password:reset {--userId=}
    // 執行 :php artisan password:reset --userId=5

    $this->option(); // 返回一個包含所有選項的陣列
    // [
    //     "userId" => "5",
    //     "help" => false,
    //     "quiet" => false,
    //     "verbose" => false,
    //     "version" => false,
    //     "ansi" => false,
    //     "no-interaction" => false,
    //     "env" => null
    // ]
    $this->option('userId');
    // "5"
}

5.3 互動式輸入資訊

在 handle() 中還有一些用於與使用者互動的方法

// 提示使用者輸入
$email = $this->ask("你的郵箱是什麼?");

// 提示使用者輸入 ,但用 "*" 隱藏輸入內容
$password = $this->secret("你的資料庫密碼是什麼?");

// 提示使用者輸入是 / 否 ,返回布林值 ,除了按 y 和 Y ,其他的輸入都會返回 false
if ($this->confirm("你確定要重置使用者的密碼?"));

// 提示使用者選擇選項 ,如果使用者沒有選擇 ,預設值就是最後一個選項
$tips = '你希望在每天什麼時間備份資料庫?'
$options = array("08:00", "20:00", "12:00");
$default = 0;
$index = $this->choice($tips, $options, $default);
// 這裡注意返回的是使用者選擇的 key ,而不是 value
print_r($optios[$index]);

// 還可以使用關聯陣列
$tips = '你現在有兩個選擇';
$options = array("a" => "自己脫", "b" => "我幫你脫");
$default = "b";
$index = $this->choice($tips, $options, $default);
print_r($optios[$index]);

5.4 向使用者提示資訊

$this->info("預設顏色的文字");
$this->comment("橙色的文字");
$this->question("青色的文字");
$this->error("紅色的文字");
$this->line("沒有顏色的文字");

5.5 輸出資料表

$headers = array('name', 'email');
$data = array(
    array('馬雲', 'jack_ma@aliyun.com'),
    array('馬化騰', 'pony@qq.com')
);
// $data = App\User::all(['name', 'email'])->toArray();
$this->table($headers, $data);
+--------+--------------------+
| name   | email              |
+--------+--------------------+
| 馬雲   | jack_ma@aliyun.com |
| 馬化騰 | pony@qq.com        |
+--------+--------------------+

5.6 進度條

// 將進度條分為 10 份
$total = 10;
// 建立進度條
$this->output->progressStart($total);
// 迴圈
for ($i = 0; $i < $total; $i++) {
    sleep(1);
    // 進度條步進
    $this->output->progressAdvance();
}
// 結束進度條
$this->output->progressFinish();
# 2
2/10 [=====>----------------------]  20%
# 10
10/10 [============================] 100%

可以用 Artisan facade 或者 Artisan::call() 來呼叫

也可以用 Artisan::queue() 將命令放到佇列中

// Artisan::call()
Route::get('test-artisan', function () { 
    $exitCode = Artisan::call("password:reset", [
        'userId' => 15, '--sendEmail' => true
    ])
})
// $this->call() 或者 $this->callSilent()
Route::get('test-artisan', function () { 
    // 這個 callSilent() 有什麼區別我也不太懂
    $exitCode = $this->callSilent("password:reset", [
        'userId' => 15, '--sendEmail' => true
    ])
})
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章