【问题标题】:Laravel write to console without impacting PHPUnitLaravel 写入控制台而不影响 PHPUnit
【发布时间】:2021-03-23 21:03:51
【问题描述】:

我想从工匠命令输出到控制台。这在很长的调用堆栈中很深,因此不适合使用 $this->error('My warning');

网上有一些解决方案建议这样做。

$out = new ConsoleOutput();
$out->writeln('My warning');

这解决了问题,但是当我运行phpunit 时,我的命令输出会干扰phpunit 的输出

vendor/bin/phpunit --filter=MyCmdTest
PHPUnit 9.3.10 by Sebastian Bergmann and contributors.

Warning:       Your XML configuration validates against a deprecated schema.
Suggestion:    Migrate your XML configuration using "--migrate-configuration"!

My warning
.

Time: 00:17.182, Memory: 56.50 MB

OK (1 test, 3 assertions)

在工匠命令深处将输出写入 cmd 行的最佳方式是什么。不影响PHPUnit的输出?

编辑

我是这样调用命令的。

$this->artisan('my:cmd')
    ->assertExitCode(0);

使用通常的$this->error() 的问题是我在 artisan 命令中做了类似的事情。

class MyCmd extends Command {
    public function handle(MyService $service) {
        $service->doStuff();
    }
}

class MyService {
    public function doStuff() {
        if (true) {
            // print a warning when the state is bad
        }
    }
}

服务被过度简化,因为服务内部的逻辑可能非常复杂,并且传递 artisan 命令的引用似乎是错误的方法。这也意味着我必须将它传递给多个服务和/或模型逻辑等。

【问题讨论】:

  • 我假设在工匠 cmd 中使用 $this->error() 不会写入 PHPUnit,所以我想一定有办法吗?
  • 它不会在 PHPUnit 中打印输出,但是当您运行 artisan 命令时会这样做,我想这可以回答吗?这也是一个问题,我如何在我的代码中相当深入地使用像 $this->error 这样的工匠助手而不通过整个调用堆栈传递引用
  • 与您在命令上下文中所做的完全一样,但在应用程序中逻辑更深,希望它有意义
  • 您能否编辑您的问题以包括您如何在测试中调用该命令,并扩展您认为$this->error()$this->info() 会产生哪些问题?
  • 我已经编辑了这个问题,这是一个相当小众和复杂的案例,我只是觉得这一定是以前出现过的。

标签: php laravel laravel-artisan


【解决方案1】:

通常在考虑关注点分离(例如 MVC 结构)时,我们会考虑 Web 上下文,将 HTML 和业务逻辑分开。但同样的事情也适用于 CLI 代码。

您的 Artisan 命令类从命令行运行,并且应该在那里输出数据。您的服务类仅用于运行其进程,不应在任何地方输出任何内容。当您想在 Web 界面的上下文中开始使用此服务类或将内容传送到文件时会发生什么?

所以你应该做的是从你的服务类中抛出一个异常,然后在更高的层次上捕获它。这允许调用代码以合适的格式输出错误消息——在这种情况下,使用Command 类中可用的方法。

class MyCmd extends Command {
    public function handle(MyService $service) {
        try {
            $service->doStuff();
        } catch (\Exception $e) {
            $this->error($e->getMessage());
        }
    }
}

class MyService {
    public function doStuff() {
        if (true) {
            // THROW a warning when the state is bad
            throw new \Exception("the state is bad!");
        }
    }
}

如果您有各种不同的错误需要以不同的方式处理,您应该考虑编写自己的异常类,因此您的代码可能看起来像这样:

class MyCmd extends Command {
    public function handle(MyService $service) {
        try {
            $service->doStuff();
        } catch (MyException $e) {
            $this->error($e->getMessage());
        } catch (MyOtherException $e) {
            do_something_else($e->someProperty);
        }
    }
}

class MyService {
    public function doStuff() {
        if (true) {
            // THROW a warning when the state is bad
            throw new MyException("the state is bad!");
        }
        if (something else) {
            $e = new MyOtherException("something else happened!");
            $e->someProperty = "foo";
            throw $e;
        }
    }
}

class MyException extends \Exception {}
class MyOtherException extends \Exception {}

【讨论】:

    猜你喜欢
    • 2013-07-22
    • 2014-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 2016-11-28
    • 1970-01-01
    相关资源
    最近更新 更多