溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Laravel中Console內(nèi)核有什么用

發(fā)布時間:2021-06-09 16:46:27 來源:億速云 閱讀:145 作者:Leah 欄目:開發(fā)技術(shù)

Laravel中Console內(nèi)核有什么用?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

內(nèi)核綁定

跟HTTP內(nèi)核一樣,在應用初始化階有一個內(nèi)核綁定的過程,將Console內(nèi)核注冊到應用的服務容器里去,還是引用上一篇文章引用過的bootstrap/app.php里的代碼

<?php
// 第一部分: 創(chuàng)建應用實例
$app = new Illuminate\Foundation\Application(
  realpath(__DIR__.'/../')
);

// 第二部分: 完成內(nèi)核綁定
$app->singleton(
  Illuminate\Contracts\Http\Kernel::class,
  App\Http\Kernel::class
);
// console內(nèi)核綁定
$app->singleton(
  Illuminate\Contracts\Console\Kernel::class,
  App\Console\Kernel::class
);

$app->singleton(
  Illuminate\Contracts\Debug\ExceptionHandler::class,
  App\Exceptions\Handler::class
);

return $app;

Console內(nèi)核 \App\Console\Kernel繼承自Illuminate\Foundation\Console, 在Console內(nèi)核中我們可以注冊artisan命令和定義應用里要執(zhí)行的計劃任務。

/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
  // $schedule->command('inspire')
  //     ->hourly();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
  $this->load(__DIR__.'/Commands');
  require base_path('routes/console.php');
}

在實例化Console內(nèi)核的時候,內(nèi)核會定義應用的命令計劃任務(shedule方法中定義的計劃任務)

public function __construct(Application $app, Dispatcher $events)
{
  if (! defined('ARTISAN_BINARY')) {
    define('ARTISAN_BINARY', 'artisan');
  }

  $this->app = $app;
  $this->events = $events;

  $this->app->booted(function () {
    $this->defineConsoleSchedule();
  });
}

應用解析Console內(nèi)核

查看aritisan文件的源碼我們可以看到, 完成Console內(nèi)核綁定的綁定后,接下來就會通過服務容器解析出console內(nèi)核對象

$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);

$status = $kernel->handle(
  $input = new Symfony\Component\Console\Input\ArgvInput,
  new Symfony\Component\Console\Output\ConsoleOutput
);

執(zhí)行命令任務

解析出Console內(nèi)核對象后,接下來就要處理來自命令行的命令請求了, 我們都知道PHP是通過全局變量$_SERVER['argv']來接收所有的命令行輸入的, 和命令行里執(zhí)行shell腳本一樣(在shell腳本里可以通過$0獲取腳本文件名,$1 $2這些依次獲取后面?zhèn)鬟f給shell腳本的參數(shù)選項)索引0對應的是腳本文件名,接下來依次是命令行里傳遞給腳本的所有參數(shù)選項,所以在命令行里通過artisan腳本執(zhí)行的命令,在artisan腳本中$_SERVER['argv']數(shù)組里索引0對應的永遠是artisan這個字符串,命令行里后面的參數(shù)會依次對應到$_SERVER['argv']數(shù)組后續(xù)的元素里。

因為artisan命令的語法中可以指定命令參數(shù)選項、有的選項還可以指定實參,為了減少命令行輸入?yún)?shù)解析的復雜度,Laravel使用了Symfony\Component\Console\Input對象來解析命令行里這些參數(shù)選項(shell腳本里其實也是一樣,會通過shell函數(shù)getopts來解析各種格式的命令行參數(shù)輸入),同樣地Laravel使用了Symfony\Component\Console\Output對象來抽象化命令行的標準輸出。

引導應用

在Console內(nèi)核的handle方法里我們可以看到和HTTP內(nèi)核處理請求前使用bootstrapper程序引用應用一樣在開始處理命令任務之前也會有引導應用這一步操作

其父類 「IlluminateFoundationConsoleKernel」 內(nèi)部定義了屬性名為 「bootstrappers」 的 引導程序 數(shù)組:

protected $bootstrappers = [
  \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
  \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
  \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
  \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
  \Illuminate\Foundation\Bootstrap\SetRequestForConsole::class,
  \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
  \Illuminate\Foundation\Bootstrap\BootProviders::class,
];

數(shù)組中包括的引導程序基本上和HTTP內(nèi)核中定義的引導程序一樣, 都是應用在初始化階段要進行的環(huán)境變量、配置文件加載、注冊異常處理器、設置Console請求、注冊應用中的服務容器、Facade和啟動服務。其中設置Console請求是唯一區(qū)別于HTTP內(nèi)核的一個引導程序。

執(zhí)行命令

執(zhí)行命令是通過Console Application來執(zhí)行的,它繼承自Symfony框架的Symfony\Component\Console\Application類, 通過對應的run方法來執(zhí)行命令。

name Illuminate\Foundation\Console;
class Kernel implements KernelContract
{
  public function handle($input, $output = null)
  {
    try {
      $this->bootstrap();

      return $this->getArtisan()->run($input, $output);
    } catch (Exception $e) {
      $this->reportException($e);

      $this->renderException($output, $e);

      return 1;
    } catch (Throwable $e) {
      $e = new FatalThrowableError($e);

      $this->reportException($e);

      $this->renderException($output, $e);

      return 1;
    }
  }
}

namespace Symfony\Component\Console;
class Application
{
  //執(zhí)行命令
  public function run(InputInterface $input = null, OutputInterface $output = null)
  {
    ......
    try {
      $exitCode = $this->doRun($input, $output);
    } catch {
      ......
    }
    ......
    return $exitCode;
  }
  
  public function doRun(InputInterface $input, OutputInterface $output)
  {
    //解析出命令名稱
    $name = $this->getCommandName($input);
    
    //解析出入?yún)?
    if (!$name) {
      $name = $this->defaultCommand;
      $definition = $this->getDefinition();
      $definition->setArguments(array_merge(
        $definition->getArguments(),
        array(
          'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
        )
      ));
    }
    ......
    try {
      //通過命令名稱查找出命令類(命名空間、類名等)
      $command = $this->find($name);
    }
    ......
    //運行命令類
    $exitCode = $this->doRunCommand($command, $input, $output);
    
    return $exitCode;
  }
  
  protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
  {
    ......
    //執(zhí)行命令類的run方法來處理任務
    $exitCode = $command->run($input, $output);
    ......
    
    return $exitcode;
  }
}

執(zhí)行命令時主要有三步操作:

  • 通過命令行輸入解析出命令名稱和參數(shù)選項。

  • 通過命令名稱查找命令類的命名空間和類名。

  • 執(zhí)行命令類的run方法來完成任務處理并返回狀態(tài)碼。

和命令行腳本的規(guī)范一樣,如果執(zhí)行命令任務程序成功會返回0, 拋出異常退出則返回1。

還有就是打開命令類后我們可以看到并沒有run方法,我們把處理邏輯都寫在了handle方法中,仔細查看代碼會發(fā)現(xiàn)run方法定義在父類中,在run方法會中會調(diào)用子類中定義的handle方法來完成任務處理。 嚴格遵循了面向?qū)ο蟪绦蛟O計的SOLID 原則。

結(jié)束應用

執(zhí)行完命令程序返回狀態(tài)碼后, 在artisan中會直接通過exit($status)函數(shù)輸出狀態(tài)碼并結(jié)束PHP進程,接下來shell進程會根據(jù)返回的狀態(tài)碼是否為0來判斷腳本命令是否執(zhí)行成功。

到這里通過命令行開啟的程序進程到這里就結(jié)束了,跟HTTP內(nèi)核一樣Console內(nèi)核在整個生命周期中也是負責調(diào)度,只不過Http內(nèi)核最終將請求落地到了Controller程序中而Console內(nèi)核則是將命令行請求落地到了Laravel中定義的各種命令類程序中,然后在命令類里面我們就可以寫其他程序一樣自由地使用Laravel中的各個組件和注冊到服務容器里的服務了。

關于Laravel中Console內(nèi)核有什么用問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業(yè)資訊頻道了解更多相關知識。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI