Я хочу вывести на консоль ремесленную команду. Это глубоко в длинном стеке вызовов, поэтому использование $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 кажется неправильным подходом. Также это означало бы, что мне пришлось передать его нескольким службам и/или логике модели и т.д.
То, что он не печатает вывод в PHPUnit, но делает это, когда вы запускаете команду artisan, я думаю, это отвечает на него? Это также вопрос, как я могу использовать помощники-ремесленники, такие как $this->error, довольно глубоко в моем коде, не передавая ссылку через весь стек вызовов.
Точно так же, как вы делаете в контексте команды, но логически глубже в приложении, надеюсь, это имеет смысл
Можете ли вы отредактировать свой вопрос, включив в него то, как вы вызываете команду в своем тесте, и уточните, какие проблемы, по вашему мнению, создадут $this->error()
или $this->info()
?
Я отредактировал вопрос, это довольно нишевый и сложный случай, я просто чувствую, что это должно было возникнуть раньше.
Обычно, когда мы думаем о разделении задач (например, структура 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>
Я предполагаю, что использование $this->error() внутри cmd ремесленника не записывает в PHPUnit, поэтому я думаю, должен быть способ?