如何巧妙地处理工匠命令中的异常

Moe*_*Moe 5 php laravel artisan lumen

使用Lumen创建一个API - 喜欢Laravel但是随之而来的所有View都对我正在创建的项目来说太过分了.

无论如何,我已经制作了一系列命令,它们会收集数据并将其存储到数据库中.

<?php 

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;

use App\User;

class GetItems extends Command {

    /**
     * The console command name.
     *
     * @var string
     */
    protected $name = 'GetItems';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = "Get items and store it into the Database";

    /**
     * Execute the console command.
     *
     * @return void
     */
    public function fire()
    {
        $this->info("Collecting ...");

       $users = User::all();

       foreach( $users as $user)
       {
           $user->getItems();
       }

   }

    /**
     * Get the console command options.
     *
     * @return array
     */
    protected function getOptions()
    {
        return [];
    }

}
Run Code Online (Sandbox Code Playgroud)

我有3个类似的命令,每个命令收集略有不同的数据集.

有没有办法我可以注入一个中间层来捕获来自fire()我的命令中的每个函数的异常?我是延长思维Command类-但想看看是否有已经是一个办法做到这一点多数民众赞成建议由框架创建者(文档/搜索并没有帮助).

我知道另一种方法是将所有命令合并到一个文件中并使用选项,但这会使它变得混乱而且难以与之协作.

有什么建议?

Cy *_*nol 6

答案取决于我们希望应用程序在命令抛出异常时执行的操作.问题没有描述处理异常的理想方法,所以让我们看一些选项.

Laravel和Lumen项目包括一个中心异常Handler类,我们可以使用它来定义不同异常的行为.此类处理从Web请求和控制台命令冒出的任何异常.

Laravel使用report()的方法的应用程序/例外/ Handler.php来决定如何记录异常.我们可以在这里添加逻辑用于错误报告:

public function report(Exception $e)  
{
    if ($e instanceof CustomConsoleException) {
        // do something specific...
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

renderForConsole()方法允许我们自定义我们希望如何显示控制台命令的错误和异常消息.项目的异常Handler通常不包含此方法定义,但如果需要,我们可以在app/Exceptions/Handler.php中覆盖它:

public function renderForConsole($output, Exception $e)
{
    $output->writeln('Something broke!'); 

    (new ConsoleApplication)->renderException($e, $output);
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,$output是对Symfony\Component\Console\Output \OutputInterface我们可以用来将文本写入控制台命令的输出流的对象的引用.

正如我们可能从上面猜到的那样,中心异常处理程序旨在处理我们的代码在较低级别不处理的未捕获异常,因此当我们需要在异常之后执行某些特定操作时它不是非常有用.以类似的方式,我们可以覆盖reportException()renderException()方法app/Console/Kernel.php.

如果我们需要做一些特定的事情,除了承认命令通过显示消息引发异常之外,我们真的应该在命令本身中编写这个逻辑.为了避免重复的代码,我们可以使用一个抽象类,三个类似的命令提供具体的实现:

abstract class AbstractGetItems extends Command 
{
    ...
    final public function fire() 
    {
        try {
            $this->getItems();
        } catch (Exception $e) {
            // handle exception... 
        }
    }

    abstract protected function getItems();
}
Run Code Online (Sandbox Code Playgroud)

此抽象命令强制子类实现getItems()该类自动调用的方法fire().我们可以为这个类添加任何其他共享逻辑.子命令只需要定义它们的具体实现getItems(),父类将处理它们的异常:

class GetSpecificItems extends AbstractGetItems 
{ 
    ... 
    protected function getItems() 
    {
        // fetch specific items...
    }
}
Run Code Online (Sandbox Code Playgroud)