Laravel 在不影响 PHPUnit 的情况下写入控制台

Laravel write to console without impacting PHPUnit

我想从 artisan 命令输出到控制台。这在很长的调用堆栈中很深,所以使用 $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)

将输出写入 artisan 命令深处的 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 命令的引用似乎是错误的方法。这也意味着我必须将它传递给多个服务和/或模型逻辑等。

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

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

所以您应该做的是从您的服务中抛出异常 class,然后在更高级别捕获它。这允许调用代码以合适的格式输出错误消息——在本例中,使用 Command class.

中可用的方法
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!");
        }
    }
}

如果您有各种不同的错误需要以不同的方式处理,您应该考虑编写自己的异常 classes,因此您的代码可能如下所示:

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

更改:

<filter> <whitelist processUncoveredFilesFromWhitelist="true"> <directory suffix=".php">./app</directory> </whitelist> </filter>

至:

<coverage processUncoveredFiles="true"> <include> <directory suffix=".php">./app</directory> </include> </coverage>

对我有用