引言
有時候為了不重寫程式碼,避免冗餘無用重複的程式碼在程式內到處都是。我們總是想方設法 把寫過的邏輯拿過來使用。
今天要說的就是在laravel中,能不能在命令列中呼叫控制器的方法, 怎麼去實現?
學習時間為了快速測試控制器方法可不可行,我們有時候會想,能不能像這樣在命令列直接訪問某個控制器路由的方法。
php index.php --uri=controller/method/var1/var2
要知道國內號稱用途最廣的thinkphp都已經這樣用了,laravel可落後乎?當然不可。
於是我們想,既然laravel提供了artisan的命令列呼叫,何不先做一個命令,然後在命令內使用程式方法 呼叫控制器呢。說來就動手開寫。
首先建立一個命令類。
php artisan make:command CallRoute
系統都是按照模板生成的 CallRoute.php 檔案,我們只撿特殊的部分貼出來。 首先定義命令格式和傳入的引數。
protected $signature = 'route:call {uri}';
然後是用法的描述:
protected $description = 'php artsian route:call /route';
要訪問uri地址,我們肯定要構造一個請求體,傳入對應的引數,這樣控制器方法才能正確地接收。
$request = Request::create($this->argument('uri'), 'GET');
這裡構造的請求體非常靈活,你可以模擬任何有效的請求,地址,方法,引數,等等。 然後重點來了,我們使用laravel框架提供的 Container 容器構造一個呼叫:
app()->make(\\Illuminate\\Contracts\\Http\\Kernel::class)->handle($request);
就醬。
為了讓你的命令在laravel生命週期內可被註冊,還需要手動註冊一下。在檔案 app/Console/Kernel.php 內加這麼一行:
protected $commands = [ 'App\\Console\\Commands\\CallRoute'];
現在你就可以在命令列使用了:
php artisan route:call /path
當然了如果你使用的laravel版本比較高,其提供了 tinker 功能,會讓你眼前一亮,相見恨晚。 比如原始的請求路由地址是這樣的:
URL: http://xxx.test/calendar?filter[id]=1&anotherparam=2
那麼我們可以直接使用容器例項化一個控制器物件:
$cc = app()->make('App\\Http\\Controllers\\CalendarController');
然後使用全域性容器盒子呼叫控制器物件的方法,並傳送引數:
app()->call([$cc, 'getCalendarV2'], ['filter[id]'=>1, 'anotherparam' => '2']);
是不是超級簡單,有沒有?可見,laravel容器盒子這種設計理念,幾乎可以跨任意區域呼叫, 提供的強大能力,非同尋常。
寫在最後本文通過詳細地設計實現了命令列呼叫控制器方法的步驟,其中低版本的推薦第一種寫法, 通過寫入請求體到框架上下文進行通訊;高版本的可以隨便開掛,容器盒子威力無比!
Happy coding :-)