鍍金池/ 教程/ PHP/ Artisan 控制臺(tái)
門面
Laravel Homestead
安裝及配置
測試
HTTP 中間件
加密
升級(jí)指南
幫助函數(shù)
應(yīng)用目錄結(jié)構(gòu)
集合
新手入門指南-簡單任務(wù)管理系統(tǒng)
任務(wù)調(diào)度
查詢構(gòu)建器
視圖
驗(yàn)證
Laravel Cashier(訂購&支付&發(fā)票)
本地化
隊(duì)列
調(diào)整器
分頁
文件系統(tǒng)/云存儲(chǔ)
貢獻(xiàn)代碼
哈希
HTTP 控制器
緩存
遷移
HTTP 請(qǐng)求
Laravel Elixir
發(fā)行版本說明
Envoy 任務(wù)運(yùn)行器(SSH任務(wù))
序列化
Session
起步
帶用戶功能的任務(wù)管理系統(tǒng)
起步
用戶授權(quán)
郵件
事件
填充數(shù)據(jù)
HTTP 路由
服務(wù)提供者
Blade 模板引擎
包開發(fā)
用戶認(rèn)證
Artisan 控制臺(tái)
HTTP 響應(yīng)
集合
服務(wù)容器
關(guān)聯(lián)關(guān)系
一次請(qǐng)求的生命周期
契約
Redis
錯(cuò)誤&日志

Artisan 控制臺(tái)

1、簡介

ArtisanLaravel 自帶的命令行接口名稱,它為你在開發(fā)過程中提供了很多有用的命令。通過強(qiáng)大的 Symfony Console 組件驅(qū)動(dòng)。想要查看所有可用的 Artisan 命令,可使用 list 命令:

php artisan list

每個(gè)命令都可以用 help 指令顯示命令描述及命令參數(shù)和選項(xiàng)。想要查看幫助界面,只需要在命令前加上 help 就可以了:

php artisan help migrate

2、編寫命令

除了 Artisan 提供的命令之外,還可以構(gòu)建自己的命令。你可以將自定義命令存放在 app/Console/Commands 目錄;當(dāng)然,你可以自己選擇存放位置,只要改命令可以基于 composer.json 被自動(dòng)加載。 要?jiǎng)?chuàng)建一個(gè)新命令,你可以使用 Artisan 命令 make:console

php artisan make:console SendEmails

上述命令將會(huì)生成一個(gè)類 app/Console/Commands/SendEmails.php,當(dāng)創(chuàng)建命令時(shí),--command 選項(xiàng)可用于分配終端命令名(在終端調(diào)用命令時(shí)用):

php artisan make:console SendEmails --command=emails:send

2.1 命令結(jié)構(gòu)

命令生成以后,需要填寫該類的 signaturedescription 屬性,這兩個(gè)屬性在調(diào)用 list 顯示命令的時(shí)候會(huì)被用到。 handle 方法在命令執(zhí)行時(shí)被調(diào)用,你可以將所有命令邏輯都放在這個(gè)方法里面,讓我們先看一個(gè)命令例子。 我們可以在命令控制器的構(gòu)造函數(shù)中注入任何依賴,Laravel服務(wù)提供者將會(huì)在構(gòu)造函數(shù)中自動(dòng)注入所有依賴類型提示。要增強(qiáng)代碼的復(fù)用性,保持代碼輕量級(jí)并讓它們延遲到應(yīng)用服務(wù)中完成任務(wù)是個(gè)不錯(cuò)的實(shí)踐:

<?php

namespace App\Console\Commands;

use App\User;
use App\DripEmailer;
use Illuminate\Console\Command;
use Illuminate\Foundation\Inspiring;

class Inspire extends Command{
    /**
     * 控制臺(tái)命令名稱
     *
     * @var string
     */
    protected $signature = 'email:send {user}';

    /**
     * 控制臺(tái)命令描述
     *
     * @var string
     */
    protected $description = 'Send drip e-mails to a user';

    /**
     * The drip e-mail service.
     *
     * @var DripEmailer
     */
    protected $drip;

    /**
     * 創(chuàng)建新的命令實(shí)例
     *
     * @param  DripEmailer  $drip
     * @return void
     */
    public function __construct(DripEmailer $drip)
    {
        parent::__construct();
        $this->drip = $drip;
    }

    /**
     * 執(zhí)行控制臺(tái)命令
     *
     * @return mixed
     */
    public function handle()
    {
        $this->drip->send(User::find($this->argument('user')));
    }
}

3、命令I(lǐng)/O

3.1 定義輸入異常

編寫控制臺(tái)命令的時(shí)候,通常通過參數(shù)和選項(xiàng)收集用戶輸入,Laravel 使這項(xiàng)操作變得很方便:在命令中使用 signature 屬性來定義我們期望的用戶輸入。signature 屬性通過一個(gè)優(yōu)雅的、路由風(fēng)格的語法允許你定義命令的名稱、參數(shù)以及選項(xiàng)。所有用戶提供的參數(shù)和選項(xiàng)都包含在大括號(hào)里:

/**
 * 控制臺(tái)命令名稱
 *
 * @var string
 */
protected $signature = 'email:send {user}';

在本例中,該命令定義了一個(gè)必須參數(shù):user。你還可以讓參數(shù)可選化并定義默認(rèn)的可選參數(shù)值:

// 選項(xiàng)參數(shù)...
email:send {user?}
// 帶默認(rèn)值的選項(xiàng)參數(shù)...
email:send {user=foo}

選項(xiàng),和參數(shù)一樣,也是用戶輸入的一種格式,不同之處在于選項(xiàng)前面有兩個(gè)短劃線(–),我們可以這樣定義選項(xiàng):

/**
 * 控制臺(tái)命令名稱
 *
 * @var string
 */
protected $signature = 'email:send {user} {--queue}';

在本例中,--queue 開關(guān)在調(diào)用 Artisan 命令的時(shí)候被指定。如果--queue 開關(guān)被傳遞,其值時(shí) true,否則其值是 false

php artisan email:send 1 --queue

你還可以指定選項(xiàng)值被用戶通過=來分配:

/**
 * 控制臺(tái)命令名稱
 *
 * @var string
 */
protected $signature = 'email:send {user} {--queue=}';

在本例中,用戶可以通過這樣的方式傳值:

php artisan email:send 1 --queue=default

還可以給選項(xiàng)分配默認(rèn)值:

email:send {user} {--queue=default}

3.1.1 輸入描述

你可以通過:分隔參數(shù)和描述來分配描述給輸入?yún)?shù)和選項(xiàng):

/**
 * 控制臺(tái)命令名稱
 *
 * @var string
 */
protected $signature = 'email:send
    {user : The ID of the user}
    {--queue= : Whether the job should be queued}';

3.2 獲取輸入

在命令被執(zhí)行的時(shí)候,很明顯,你需要訪問命令獲取的參數(shù)和選項(xiàng)的值。使用 argumentoption 方法即可實(shí)現(xiàn): 要獲取參數(shù)的值,通過 argument 方法:

/**
 * 執(zhí)行控制臺(tái)命令
 *
 * @return mixed
 */
public function handle(){
    $userId = $this->argument('user');
}

如果你需要以數(shù)組形式獲取所有參數(shù)值,使用不帶參數(shù)的 argument

$arguments = $this->argument();

選項(xiàng)值和參數(shù)值的獲取一樣簡單,使用 option 方法,同 argument 一樣如果要獲取所有選項(xiàng)值,可以調(diào)用不帶參數(shù)的 option 方法:

// 獲取指定選項(xiàng)...
$queueName = $this->option('queue');
// 獲取所有選項(xiàng)...
$options = $this->option();

如果參數(shù)或選項(xiàng)不存在,返回 null。

3.3 輸入提示

除了顯示輸出之外,你可能還要在命令執(zhí)行期間要用戶提供輸入。ask 方法將會(huì)使用給定問題提示用戶,接收輸入,然后返回用戶輸入到命令:

/**
 * 執(zhí)行控制臺(tái)命令
 *
 * @return mixed
 */
public function handle(){
    $name = $this->ask('What is your name?');
}

secret 方法和 ask 方法類似,但用戶輸入在終端對(duì)他們而言是不可見的,這個(gè)方法在問用戶一些敏感信息如密碼時(shí)很有用:

$password = $this->secret('What is the password?');

3.3.1 讓用戶確認(rèn)

如果你需要讓用戶確認(rèn)信息,可以使用 confirm 方法,默認(rèn)情況下,該方法返回 false,如果用戶輸入 y,則該方法返回 true

if ($this->confirm('Do you wish to continue? [y|N]')) {
    //
}

3.3.2 給用戶提供選擇

anticipate 方法可用于為可能的選項(xiàng)提供自動(dòng)完成功能,用戶仍然可以選擇答案,而不管這些選擇:

$name = $this->anticipate('What is your name?', ['Taylor', 'Dayle']);

如果你需要給用戶預(yù)定義的選擇,可以使用 choice 方法。用戶選擇答案的索引,但是返回給你的是答案的值。如果用戶什么都沒選的話你可以設(shè)置默認(rèn)返回的值:

$name = $this->choice('What is your name?', ['Taylor', 'Dayle'], false);

3.4 編寫輸出

要將輸出發(fā)送到控制臺(tái),使用 info, comment, questionerror方法,每個(gè)方法都會(huì)使用相應(yīng)的 ANSI 顏色以作標(biāo)識(shí)。 要顯示一條信息消息給用戶,使用 info 方法。通常,在終端顯示為綠色:

/**
 * 執(zhí)行控制臺(tái)命令
 *
 * @return mixed
 */
public function handle(){
    $this->info('Display this on the screen');
}

要顯示一條錯(cuò)誤消息,使用 error 方法。錯(cuò)誤消息文本通常是紅色:

$this->error('Something went wrong!');

3.4.1 表格布局

table 方法使輸出多行/列格式的數(shù)據(jù)變得簡單,只需要將頭和行傳遞給該方法,寬度和高度將基于給定數(shù)據(jù)自動(dòng)計(jì)算:

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

3.4.2 進(jìn)度條

對(duì)需要較長時(shí)間運(yùn)行的任務(wù),顯示進(jìn)度指示器很有用,使用該輸出對(duì)象,我們可以開始、前進(jìn)以及停止該進(jìn)度條。在開始進(jìn)度時(shí)你必須定義定義步數(shù),然后每走一步進(jìn)度條前進(jìn)一格:

$users = App\User::all();

$this->output->progressStart(count($users));

foreach ($users as $user) {
    $this->performTask($user);
    $this->output->progressAdvance();
}

$this->output->progressFinish();

想要了解更多,查看 Symfony 進(jìn)度條組件文檔。

4、注冊(cè)命令

命令編寫完成后,需要注冊(cè)到 Artisan 才可以使用,這可以在 app/Console/Kernel.php 文件中完成。

在該文件中,你會(huì)在 commans 屬性中看到一個(gè)命令列表,要注冊(cè)你的命令,只需將加到該列表中即可。當(dāng) Artisan 啟動(dòng)的時(shí)候,該屬性中列出的命令將會(huì)被服務(wù)容器解析被注冊(cè)到 Artisan

protected $commands = [
    'App\Console\Commands\SendEmails'
];

5、通過代碼調(diào)用命令

有時(shí)候你可能希望在 CLI 之外執(zhí)行 Artisan 命令,比如,你可能希望在路由或控制器中觸發(fā) Artisan 命令,你可以使用 Artisan 門面上的 call 方法來完成這個(gè)。call 方法接收被執(zhí)行的命令名稱作為第一個(gè)參數(shù),命令參數(shù)數(shù)組作為第二個(gè)參數(shù),退出代碼被返回:

Route::get('/foo', function () {
    $exitCode = Artisan::call('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);
});

使用 Artisan 上的 queue 方法,你甚至可以將 Artisan 命令放到隊(duì)列中,這樣它們就可以通過后臺(tái)的隊(duì)列工作者來處理:

Route::get('/foo', function () {
    Artisan::queue('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);
});

如果你需要指定不接收字符串的選項(xiàng)值,例如 migrate:refresh 命令上的--force 標(biāo)識(shí),可以傳遞布爾值 truefalse

$exitCode = Artisan::call('migrate:refresh', [
    '--force' => true,
]);

5.1 通過其他命令調(diào)用命令

有時(shí)候你希望從一個(gè)已存在的 Artisan 命令中調(diào)用其它命令。你可以通過使用 call 方法開實(shí)現(xiàn)這一目的。call 方法接收命令名稱和數(shù)組形式的命令參數(shù):

/**
 * 執(zhí)行控制臺(tái)命令
 *
 * @return mixed
 */
public function handle(){
    $this->call('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);
}

如果你想要調(diào)用其它控制臺(tái)命令并阻止其所有輸出,可以使用 callSilent 方法。

callSilent 方法和 call 方法用法一致:
$this->callSilent('email:send', [
    'user' => 1, '--queue' => 'default'
]);