Laravel записывает в консоль, не влияя на PHPUnit

Я хочу вывести на консоль ремесленную команду. Это глубоко в длинном стеке вызовов, поэтому использование $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 глубоко внутри команды artisan. Не влияя на вывод 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 кажется неправильным подходом. Также это означало бы, что мне пришлось передать его нескольким службам и/или логике модели и т.д.

Я предполагаю, что использование $this->error() внутри cmd ремесленника не записывает в PHPUnit, поэтому я думаю, должен быть способ?

mrhn 12.12.2020 19:48

То, что он не печатает вывод в PHPUnit, но делает это, когда вы запускаете команду artisan, я думаю, это отвечает на него? Это также вопрос, как я могу использовать помощники-ремесленники, такие как $this->error, довольно глубоко в моем коде, не передавая ссылку через весь стек вызовов.

mrhn 12.12.2020 19:52

Точно так же, как вы делаете в контексте команды, но логически глубже в приложении, надеюсь, это имеет смысл

mrhn 12.12.2020 19:56

Можете ли вы отредактировать свой вопрос, включив в него то, как вы вызываете команду в своем тесте, и уточните, какие проблемы, по вашему мнению, создадут $this->error() или $this->info()?

miken32 12.12.2020 19:59

Я отредактировал вопрос, это довольно нишевый и сложный случай, я просто чувствую, что это должно было возникнуть раньше.

mrhn 12.12.2020 20:07
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
5
1 903
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Обычно, когда мы думаем о разделении задач (например, структура MVC), мы думаем о веб-контексте, разделяя HTML и бизнес-логику. Но то же самое относится и к коду CLI.

Ваш командный класс Artisan запускается из командной строки и должен выводить туда данные. Ваш класс обслуживания предназначен исключительно для запуска своих процессов и не должен никуда ничего выводить. Что происходит, когда вы хотите начать использовать этот класс службы в контексте веб-интерфейса или передать содержимое в файл?

Итак, что вам следует делать, так это генерировать исключение из вашего класса обслуживания, а затем перехватывать его на более высоком уровне. Это позволяет вызывающему коду выводить сообщение об ошибке в подходящем формате — в данном случае с использованием методов, доступных в классе 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 {}

изменять :

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

к :

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

Другие вопросы по теме