Laravel Commands

栏目: CSS · CSS3 · 发布时间: 7年前

内容简介:有用的就两句:

Laravel Command机制原理

图解

Laravel Commands

代码解释

handle方法

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;
        }
    }

有用的就两句:

$this->bootstrap();
 return $this->getArtisan()->run($input, $output);

bootstrap() 方法,用来启动引导程序,这个方法的内容:

public function bootstrap()
    {
         // hasBeenBootstrapped 是一个标记,标记当前程序是否执行过引导程序
        if (! $this->app->hasBeenBootstrapped()) {
              // 开始引导
            $this->app->bootstrapWith($this->bootstrappers());
        }

        // 执行最终引导
        $this->app->loadDeferredProviders();

         // 
        if (! $this->commandsLoaded) {
            $this->commands();

            $this->commandsLoaded = true;
        }
    }

其中 $this->bootstrappers() 方法只是返回定义好的一个数组,即需要执行的的对象组

他们是

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,
    ];

作用基本上就是初始化各种数据,比如第一个 \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class , 就是用来初始化访问 .env 文件的函数的.

得到了数组后,会调用容器的 bootstrapWith 方法,用来开始引导

public function bootstrapWith(array $bootstrappers)
    {
        // 设置当前已经经过引导,与上面的hasBeenBootstrapped()方法对应
        $this->hasBeenBootstrapped = true;

        foreach ($bootstrappers as $bootstrapper) {
        
            // 这里只是为了记录些引导过程,不必多看
            $this['events']->fire('bootstrapping: '.$bootstrapper, [$this]);

            // 从容器中实例化出当前引导类,并执行这个类的bootstrap方法
            $this->make($bootstrapper)->bootstrap($this);

             // 标记引导完成
            $this['events']->fire('bootstrapped: '.$bootstrapper, [$this]);
        }
    }

接下来会执行最终的引导程序:

public function loadDeferredProviders()
    {
        // We will simply spin through each of the deferred providers and register each
        // one and boot them if the application has booted. This should make each of
        // the remaining services available to this application for immediate use.
        foreach ($this->deferredServices as $service => $provider) {
            $this->loadDeferredProvider($service);
        }
        $this->deferredServices = [];
    }

这里实际上是针对第三方的 provider 进行注册,大体思路和服务容器中内置 provider 的注册相同

接下来判断是否加载了Command环境, $this->commands 方法,但是这里的方法体是空的,不知道这里有什么用处

最开始的第一行代码就到这里,接下来是 $this->getArtisan()

这个方法是新建一个容器(这个容器是Console的Application)

然后执行这个容器的 resolveCommands 方法,这个方法会遍历所有注册的commands 并且对每个命令,都实例化一个类,并使用add方法添加到公共属性中(包括别名的设定之类的)

接下来是最终要的 run 方法:

public function run(InputInterface $input = null, OutputInterface $output = null)
    {
        $commandName = $this->getCommandName(
            $input = $input ?: new ArgvInput
        );

        $this->events->fire(
            new Events\CommandStarting(
                $commandName, $input, $output = $output ?: new ConsoleOutput
            )
        );

        $exitCode = parent::run($input, $output);

        $this->events->fire(
            new Events\CommandFinished($commandName, $input, $output, $exitCode)
        );

        return $exitCode;
    }

有用的只有中间一句 ` $exitCode = parent::run($input, $output);`

这个方法里面又对输入和输出进行了各种格式化操作,让显示更加人性化

整个run方法里的核心也只有一个 doRun 方法:

public function doRun(InputInterface $input, OutputInterface $output)
    {
        if (true === $input->hasParameterOption(array('--version', '-V'), true)) {
            $output->writeln($this->getLongVersion());

            return 0;
        }

        // 1. 从输入中获取输入的命令名
        $name = $this->getCommandName($input);
        if (true === $input->hasParameterOption(array('--help', '-h'), true)) {
            if (!$name) {
                $name = 'help';
                $input = new ArrayInput(array('command_name' => $this->defaultCommand));
            } else {
                $this->wantHelps = true;
            }
        }

        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 {
            $this->runningCommand = null;
            // the command name MUST be the first element of the input
            $command = $this->find($name);
        } catch (\Throwable $e) {
            if (!($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException) || 1 !== count($alternatives = $e->getAlternatives()) || !$input->isInteractive()) {
                if (null !== $this->dispatcher) {
                    $event = new ConsoleErrorEvent($input, $output, $e);
                    $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event);

                    if (0 === $event->getExitCode()) {
                        return 0;
                    }

                    $e = $event->getError();
                }

                throw $e;
            }

            $alternative = $alternatives[0];

            $style = new SymfonyStyle($input, $output);
            $style->block(sprintf("\nCommand \"%s\" is not defined.\n", $name), null, 'error');
            if (!$style->confirm(sprintf('Do you want to run "%s" instead? ', $alternative), false)) {
                if (null !== $this->dispatcher) {
                    $event = new ConsoleErrorEvent($input, $output, $e);
                    $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event);

                    return $event->getExitCode();
                }

                return 1;
            }

            $command = $this->find($alternative);
        }

        $this->runningCommand = $command;
        $exitCode = $this->doRunCommand($command, $input, $output);
        $this->runningCommand = null;

        return $exitCode;
    }

又是一堆准备的方法,核心是最下面的 $this->doRunCommand($command, $input, $output); 这句

然后再继续跟下来… 不想在写了,都是做各种初始化,到最后调用 commandhandle 方法即可,

然后得到的输出又经过一堆的操作显示在控制台里…..


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Beautiful Code

Beautiful Code

Greg Wilson、Andy Oram / O'Reilly Media / 2007-7-6 / GBP 35.99

In this unique work, leading computer scientists discuss how they found unusual, carefully designed solutions to difficult problems. This book lets the reader look over the shoulder of major coding an......一起来看看 《Beautiful Code》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具