本篇文章給大家?guī)砹岁P(guān)于Laravel的相關(guān)知識,其中主要介紹了運(yùn)行命令行腳本的相關(guān)問題,Laravel 中有個專門單獨(dú)的目錄,也就是 Console 目錄,它是用于存放腳本文件的。下面一起來看一下,希望對大家有幫助。
推薦學(xué)習(xí):Laravel入門
我們看到了 Laravel 中有個專門單獨(dú)的目錄,也就是 Console 目錄,它是用于存放腳本文件的。這個腳本文件一般指的就是我們通過 php 命令來執(zhí)行的命令行腳本,在許多框架中都有這樣的功能。對于現(xiàn)代化的應(yīng)用開發(fā)來說,一些數(shù)據(jù)統(tǒng)計、數(shù)據(jù)導(dǎo)出、隊(duì)列處理等比較耗時的功能,以及一些自動化的后端運(yùn)行程序,都需要使用這種命令行腳本來執(zhí)行。
默認(rèn)提供的腳本
在當(dāng)前的框架目錄中,我們在根目錄執(zhí)行 php artisan ,就可以看到命令行的幫助信息,這里就列出了所有已經(jīng)存在的命令行腳本。第一篇文章中,我們就接觸過這其中的兩個命令。
# php artisan key:generate # php artisan serve
它們的作用一個是生成一個加密緩存等需要使用的唯一 Key ,另一個是運(yùn)行一個自帶的簡易服務(wù)器。從腳本名稱中我們可以看出,腳本可以以一個 : 分隔,冒號前面是大的分類,比如有 cache:xxx 相關(guān)的,也有 make:xxx 相關(guān)的。cache 相關(guān)的就是處理一些緩存信息的,而 make 相關(guān)的則是創(chuàng)建一些我們需要的文件,比如創(chuàng)建一個控制器可以使用 make:controller ,創(chuàng)建一個數(shù)據(jù)模型可以使用 make:model 。
關(guān)于這些默認(rèn)自帶的腳本,我們將在學(xué)習(xí)到相關(guān)內(nèi)容的時候順帶著一起學(xué)習(xí)。
自定義一個腳本
自定義一個腳本非常簡單。我們可以使用 make:command 命令來生成一個命令行腳本。
# php artisan make:command test1 Console command created successfully.
這時,在 app/Console/Commands 目錄下就會出現(xiàn)一個 test1.php 文件。打開這個文件,我們需要做一些修改。
/** * The name and signature of the console command. * * @var string */ protected $signature = 'command:name'; /** * The console command description. * * @var string */ protected $description = 'Command description';
signature 用于設(shè)定當(dāng)前這個腳本的名稱,description 用于定義腳本的注釋說明。它們用在什么地方呢?其實(shí) signature 就是我們通過 php artisan 來運(yùn)行這個腳本時所需要用到的那個名稱。比如我們現(xiàn)在直接執(zhí)行 php artisan 的話,就會看到下面這樣一條可執(zhí)行命令行腳本的出現(xiàn)。
command command:name Command description
當(dāng)然,使用這個默認(rèn)的名稱并不是好的主意,所以我們可以修改一下這兩個屬性。
/** * The name and signature of the console command. * * @var string */ protected $signature = 'ZyBlog:Test1'; /** * The console command description. * * @var string */ protected $description = '硬核測試1';
這個時候我們再運(yùn)行 php artisan 的話,就可以看到我們定義的信息了。
ZyBlog ZyBlog:Test1 硬核測試1
如果要運(yùn)行這個腳本也非常簡單。
# php artisan ZyBlog:Test1
當(dāng)然,我們還什么都沒做呢,所以不會有什么輸出。接下來我們把接收參數(shù)和輸出信息一起做了。接收參數(shù)需要在 signature 中定義我們要接收的參數(shù)及選項(xiàng)。還記得我們之前講過的在 PHP 中如何接收腳本參數(shù)及選項(xiàng)信息的文章嗎?Laravel 已經(jīng)將這些封裝好了,不需要再去使用那些函數(shù)來進(jìn)行接收處理,直接使用就可以了。需要復(fù)習(xí)的同學(xué)可以移步 【如何獲取PHP命令行參數(shù)】mp.weixin.qq.com/s/dFuGaM1JT… 進(jìn)行復(fù)習(xí)或?qū)W習(xí)。
protected $signature = 'ZyBlog:Test1 {a=1} {--b=*}'; /** * Execute the console command. * * @return int */ public function handle() { echo "歡迎進(jìn)來測試!", PHP_EOL; print_r($this->arguments()); // Array // ( // [command] => ZyBlog:Test1 // [a] => 1 // ) print_r($this->options()); // Array // ( // [b] => Array // ( // [0] => 2 // ) // [help] => // [quiet] => // [verbose] => // [version] => // [ansi] => // [no-ansi] => // [no-interaction] => // [env] => // ) echo $this->argument('a'); // 1 print_r($this->option('b')); // Array // ( // [0] => 2 // ) return 0; }
在 handle() 函數(shù)中,我們可以編寫當(dāng)前這個腳本需要執(zhí)行的功能代碼。其中,通過 arguments() 和 argument() 可以接收到腳本的參數(shù)信息,通過 options() 和 option() 可以接收到腳本的選項(xiàng)信息。關(guān)于參數(shù)和選項(xiàng)的問題,之前的文章中我們也講解過了,這里也就不多說了,一切都是以基礎(chǔ)為準(zhǔn)的。
參數(shù)選項(xiàng)源碼分析
對于參數(shù)和選項(xiàng)來說,Laravel 的底層調(diào)用的其實(shí)是 symfony 的 Console 組件,在 symfony/console/Input/ArgvInput.php 中,我們可以看到下面這些代碼。
public function __construct(array $argv = null, InputDefinition $definition = null) { $argv = $argv ?? $_SERVER['argv'] ?? []; // strip the application name array_shift($argv); $this->tokens = $argv; parent::__construct($definition); } // …………………… // …………………… protected function parse() { $parseOptions = true; $this->parsed = $this->tokens; while (null !== $token = array_shift($this->parsed)) { if ($parseOptions && '' == $token) { $this->parseArgument($token); } elseif ($parseOptions && '--' == $token) { $parseOptions = false; } elseif ($parseOptions && 0 === strpos($token, '--')) { $this->parseLongOption($token); } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { $this->parseShortOption($token); } else { $this->parseArgument($token); } } }
很明顯,在 symfony 中,也是使用的 argv 獲取參數(shù)和選項(xiàng),然后將它們放到 input 變量中向下傳遞。這個 input 變量很重要,后面我們在學(xué)習(xí)請求相關(guān)的內(nèi)容時也會接觸到。之后在我們的執(zhí)行代碼中,也就是 Command 的 handle() 方法中使用 argument() 或者 option() 獲取到的就是這個 input 中的數(shù)據(jù)。從斷點(diǎn)調(diào)試中我們就可以看到它們的身影。
那么 Laravel 是如何執(zhí)行 handle() 函數(shù)的呢?首先通過 artisan 文件調(diào)用到 laravel/framework/src/Illuminate/Foundation/Console/Kernel.php 文件,在這個 Kernel.php 中的 handle() 方法中會調(diào)用 symfony/console/Application.php ,接著進(jìn)入 laravel/framework/src/Illuminate/Console/Command.php 中執(zhí)行 execute() 方法,通過回調(diào)的方式調(diào)用我們自定義的那個 handle() 方法。
注意,在 laravel/framework/src/Illuminate/Console/Command.php 的底層還是調(diào)用的 symfony 下面的 console/command.php 里面的方法。
整個調(diào)用鏈條非常長,不過也可以清晰地看出我們的 Laravel 確實(shí)就是在 Symfony 的基礎(chǔ)上又套了層殼。而且不僅僅是命令行這里,在 Web 請求這一塊,依然底層還是 Symfony 在發(fā)揮著至關(guān)重要的作用。
推薦學(xué)習(xí):Laravel視頻教程