• 售前

  • 售后

热门帖子
入门百科

浅谈Laravel焦点解读之Console内核

[复制链接]
看不清从bm 显示全部楼层 发表于 2021-10-26 13:03:24 |阅读模式 打印 上一主题 下一主题
Console内核

上一篇文章我们先容了Laravel的HTTP内核,具体概述了网络请求从进入应用到应用处理完请求返回HTTP相应整个生命周期中HTTP内核是怎样调动Laravel各个核心组件来完成任务的。除了处理HTTP请求一个健壮的应用常常还会必要实验筹划任务、异步队列这些。Laravel为了能让应用满足这些场景设计了artisan工具,通过artisan工具界说各种下令来满足非HTTP请求的各种场景,artisan下令通过Laravel的Console内核来完成对应用核心组件的调理来完成任务。 本日我们就来学习一下Laravel Console内核的核心代码。
内核绑定

跟HTTP内核一样,在应用初始化阶有一个内核绑定的过程,将Console内核注册到应用的服务容器里去,还是引用上一篇文章引用过的bootstrap/app.php里的代码
  1. <?php
  2. // 第一部分: 创建应用实例
  3. $app = new Illuminate\Foundation\Application(
  4.   realpath(__DIR__.'/../')
  5. );
  6. // 第二部分: 完成内核绑定
  7. $app->singleton(
  8.   Illuminate\Contracts\Http\Kernel::class,
  9.   App\Http\Kernel::class
  10. );
  11. // console内核绑定
  12. $app->singleton(
  13.   Illuminate\Contracts\Console\Kernel::class,
  14.   App\Console\Kernel::class
  15. );
  16. $app->singleton(
  17.   Illuminate\Contracts\Debug\ExceptionHandler::class,
  18.   App\Exceptions\Handler::class
  19. );
  20. return $app;
复制代码
Console内核
  1. \App\Console\Kernel
复制代码
继承自
  1. Illuminate\Foundation\Console,
复制代码
在Console内核中我们可以注册artisan下令和界说应用里要实验的筹划任务。
  1. /**
  2. * Define the application's command schedule.
  3. *
  4. * @param \Illuminate\Console\Scheduling\Schedule $schedule
  5. * @return void
  6. */
  7. protected function schedule(Schedule $schedule)
  8. {
  9.   // $schedule->command('inspire')
  10.   //     ->hourly();
  11. }
  12. /**
  13. * Register the commands for the application.
  14. *
  15. * @return void
  16. */
  17. protected function commands()
  18. {
  19.   $this->load(__DIR__.'/Commands');
  20.   require base_path('routes/console.php');
  21. }
复制代码
在实例化Console内核的时间,内核会界说应用的下令筹划任务(shedule方法中界说的筹划任务)
  1. public function __construct(Application $app, Dispatcher $events)
  2. {
  3.   if (! defined('ARTISAN_BINARY')) {
  4.     define('ARTISAN_BINARY', 'artisan');
  5.   }
  6.   $this->app = $app;
  7.   $this->events = $events;
  8.   $this->app->booted(function () {
  9.     $this->defineConsoleSchedule();
  10.   });
  11. }
复制代码
应用解析Console内核

查看
  1. aritisan
复制代码
文件的源码我们可以看到, 完成Console内核绑定的绑定后,接下来就会通过服务容器解析出console内核对象
  1. $kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
  2. $status = $kernel->handle(
  3.   $input = new Symfony\Component\Console\Input\ArgvInput,
  4.   new Symfony\Component\Console\Output\ConsoleOutput
  5. );
复制代码
实验下令任务

解析出Console内核对象后,接下来就要处理来自下令行的下令请求了, 我们都知道PHP是通过全局变量$_SERVER['argv']来吸收全部的下令行输入的, 和下令行里实验shell脚本一样(在shell脚本里可以通过$0获取脚本文件名,$1 $2这些依次获取后面通报给shell脚本的参数选项)索引0对应的是脚本文件名,接下来依次是下令行里通报给脚本的全部参数选项,以是在下令行里通过artisan脚本实验的下令,在artisan脚本中$_SERVER['argv']数组里索引0对应的永远是artisan这个字符串,下令行里后面的参数会依次对应到$_SERVER['argv']数组后续的元素里。
因为artisan下令的语法中可以指定下令参数选项、有的选项还可以指定实参,为了减少下令行输入参数解析的复杂度,Laravel使用了Symfony\Component\Console\Input对象来解析下令行里这些参数选项(shell脚本里其实也是一样,会通过shell函数getopts来解析各种格式的下令行参数输入),同样地Laravel使用了Symfony\Component\Console\Output对象来抽象化下令行的尺度输出。
引导应用

在Console内核的handle方法里我们可以看到和HTTP内核处理请求前使用bootstrapper步伐引用应用一样在开始处理下令任务之前也会有引导应用这一步操纵
其父类 「IlluminateFoundationConsoleKernel」 内部界说了属性名为 「bootstrappers」 的 引导步伐 数组:
  1. protected $bootstrappers = [
  2.   \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
  3.   \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
  4.   \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
  5.   \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
  6.   \Illuminate\Foundation\Bootstrap\SetRequestForConsole::class,
  7.   \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
  8.   \Illuminate\Foundation\Bootstrap\BootProviders::class,
  9. ];
复制代码
数组中包罗的引导步伐根本上和HTTP内核中界说的引导步伐一样, 都是应用在初始化阶段要举行的情况变量、配置文件加载、注册非常处理器、设置Console请求、注册应用中的服务容器、Facade和启动服务。此中设置Console请求是唯一区别于HTTP内核的一个引导步伐。
实验下令

实验下令是通过Console Application来实验的,它继承自Symfony框架的Symfony\Component\Console\Application类, 通过对应的run方法来实验下令。
  1. name Illuminate\Foundation\Console;
  2. class Kernel implements KernelContract
  3. {
  4.   public function handle($input, $output = null)
  5.   {
  6.     try {
  7.       $this->bootstrap();
  8.       return $this->getArtisan()->run($input, $output);
  9.     } catch (Exception $e) {
  10.       $this->reportException($e);
  11.       $this->renderException($output, $e);
  12.       return 1;
  13.     } catch (Throwable $e) {
  14.       $e = new FatalThrowableError($e);
  15.       $this->reportException($e);
  16.       $this->renderException($output, $e);
  17.       return 1;
  18.     }
  19.   }
  20. }
  21. namespace Symfony\Component\Console;
  22. class Application
  23. {
  24.   //执行命令
  25.   public function run(InputInterface $input = null, OutputInterface $output = null)
  26.   {
  27.     ......
  28.     try {
  29.       $exitCode = $this->doRun($input, $output);
  30.     } catch {
  31.       ......
  32.     }
  33.     ......
  34.     return $exitCode;
  35.   }
  36.   
  37.   public function doRun(InputInterface $input, OutputInterface $output)
  38.   {
  39.     //解析出命令名称
  40.     $name = $this->getCommandName($input);
  41.    
  42.     //解析出入参
  43.     if (!$name) {
  44.       $name = $this->defaultCommand;
  45.       $definition = $this->getDefinition();
  46.       $definition->setArguments(array_merge(
  47.         $definition->getArguments(),
  48.         array(
  49.           'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
  50.         )
  51.       ));
  52.     }
  53.     ......
  54.     try {
  55.       //通过命令名称查找出命令类(命名空间、类名等)
  56.       $command = $this->find($name);
  57.     }
  58.     ......
  59.     //运行命令类
  60.     $exitCode = $this->doRunCommand($command, $input, $output);
  61.    
  62.     return $exitCode;
  63.   }
  64.   
  65.   protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
  66.   {
  67.     ......
  68.     //执行命令类的run方法来处理任务
  69.     $exitCode = $command->run($input, $output);
  70.     ......
  71.    
  72.     return $exitcode;
  73.   }
  74. }
复制代码
实验下令时重要有三步操纵:
      
  • 通过下令行输入解析出下令名称和参数选项。  
  • 通过下令名称查找下令类的定名空间和类名。  
  • 实验下令类的run方法来完成任务处理并返回状态码。
和下令行脚本的规范一样,假如实验下令任务步伐成功会返回0, 抛出非常退出则返回1。
另有就是打开下令类后我们可以看到并没有run方法,我们把处理逻辑都写在了handle方法中,细致查看代码会发现run方法界说在父类中,在run方法会中会调用子类中界说的handle方法来完成任务处理。 严格遵照了面向对象步伐设计的SOLID 原则。
结束应用

实验完下令步伐返回状态码后, 在artisan中会直接通过exit($status)函数输出状态码并结束PHP进程,接下来shell进程会根据返回的状态码是否为0来判断脚本下令是否实验成功。
到这里通过下令行开启的步伐进程到这里就结束了,跟HTTP内核一样Console内核在整个生命周期中也是负责调理,只不外Http内核终极将请求落地到了Controller步伐中而Console内核则是将下令行请求落地到了Laravel中界说的各种下令类步伐中,然后在下令类内里我们就可以写其他步伐一样自由地使用Laravel中的各个组件和注册到服务容器里的服务了。
本文已经收录在系列文章Laravel源码学习里,接待访问阅读。

以上就是本文的全部内容,盼望对各人的学习有所帮助,也盼望各人多多支持脚本之家。

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作