如何巧妙地处理Artisan Commands中的异常 [英] How to neatly handle Exceptions in Artisan Commands

查看:60
本文介绍了如何巧妙地处理Artisan Commands中的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Lumen创建API-喜欢Laravel,但它附带的所有View对于我正在创建的项目来说都是过分的.

Using Lumen to create an API - love Laravel but all the View's that come with it were overkill for the project I am creating.

无论如何,我做出了一系列命令,这些命令可以收集数据并将其存储到数据库中.

Anyway, I've made a series of Commands which go out and collect data and stores it to the database.

<?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 [];
    }

}

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

I've got 3 similar commands, each one collecting slightly different datasets.

有没有办法注入一个中间层,该中间层捕获我的Command中每个fire()函数所产生的异常?我当时正在考虑扩展Command类-但想看看是否已经有框架创建者推荐的方法(文档/搜索没有帮助).

Is there a way I can inject a middle-layer that catches an exception that comes from each of the fire() functions across my Commands? I was thinking of extending the Command Class - but wanted to see if there's already a way to do it that's recommended by the Framework creators (documentation/searching was no help).

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

I know the alternative would be to combine all the commands into one file and use options, but this makes it messy and harder to collaborate with.

有什么建议吗?

推荐答案

答案取决于我们希望应用程序在命令引发异常时执行的操作.这个问题并未描述处理异常的理想方式,因此让我们看一些选项.

The answer depends on what we want the application to do when the command throws an exception. The question doesn't describe a desired way to handle the exception, so let's look at a few options.

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

Laravel and Lumen projects include a central exception Handler class that we can use to define behaviors for different exceptions. This class handles any exceptions that bubble up from web requests and console commands.

Laravel使用 app/Exceptions/Handler.php 中的report()方法来确定如何记录异常.我们可以在此处为错误报告添加逻辑:

Laravel uses the report() method in app/Exceptions/Handler.php to determine how to log an exception. We can add logic here for error reporting:

public function report(Exception $e)  
{
    if ($e instanceof CustomConsoleException) {
        // do something specific...
    }
    ...
}

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

The renderForConsole() method lets us customize how we want to display error and exception messages for console commands. The project's exception Handler usually doesn't contain this method definition, but we can override it in app/Exceptions/Handler.php if needed:

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

    (new ConsoleApplication)->renderException($e, $output);
}

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

In the example above, $output is a reference to a Symfony\Component\Console\Output \OutputInterface object that we can use to write text to the console command's output streams.

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

As we might guess from above, the central exception handler is designed to deal with uncaught exceptions that our code doesn't handle at a lower level, so it's not very useful when we need to execute some specific action after an exception. In a similar fashion, we could override the reportException() and renderException() methods in app/Console/Kernel.php.

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

If we need to do something specific besides just acknowledging that a command threw an exception by showing a message, we really should write this logic in the command itself. To avoid duplicate code, we could use an abstract class that the three similar commands provide concrete implementations for:

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

    abstract protected function getItems();
}

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

This abstract command forces child classes to implement the getItems() method, which the class calls automatically in fire(). We can add any other shared logic to this class. The child commands need only to define their specific implementation of getItems(), and the parent class will handle exceptions for them:

class GetSpecificItems extends AbstractGetItems 
{ 
    ... 
    protected function getItems() 
    {
        // fetch specific items...
    }
}

这篇关于如何巧妙地处理Artisan Commands中的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆