Как отобразить трассировку Exception в команде laravel console?
Я использую Laravel 5.1 для создания консольного приложения. Во время разработки я хотел бы отобразить трассировку исключения при возникновении ошибки. Однако, даже если я использую опцию -v -vv или -vvv в php artisan
, я не получаю трассировку исключения для моих пользовательских команд. Я установил APP_DEBUG=true
в мой .env
, все еще не отслеживая трассировку исключений.
Вывод php artisan some:unknowncommand
:
[InvalidArgumentException]
There are no commands defined in the "some" namespace.
Вывод php artisan -v some:unknowncommand
:
[InvalidArgumentException]
There are no commands defined in the "some" namespace.
Exception trace:
() at /Users/dirkpostma/Dropbox/Domains/dpepp/vendor/symfony/console/Application.php:501
Symfony\Component\Console\Application->findNamespace() at /Users/dirkpostma/Dropbox/Domains/dpepp/vendor/symfony/console/Application.php:535
Symfony\Component\Console\Application->find() at /Users/dirkpostma/Dropbox/Domains/dpepp/vendor/symfony/console/Application.php:192
Symfony\Component\Console\Application->doRun() at /Users/dirkpostma/Dropbox/Domains/dpepp/vendor/symfony/console/Application.php:126
...
Теперь я создал очень простую консольную команду под названием dp: test со следующей функцией дескриптора:
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
generate error here
}
Вывод php artisan dp:test
:
[Symfony\Component\Debug\Exception\FatalErrorException]
syntax error, unexpected 'error' (T_STRING)
Вывод php artisan -v dp:test
одинаков.
Вывод php artisan -vvv dp:test
одинаков.
В файле журнала DOES показана трассировка исключения, поэтому каким-то образом ее можно отобразить в cli. Я даже не вижу имя файла и linenumer, где возникает ошибка... Как я могу позаботиться об этом?
Спасибо заранее!
EDIT:
Копается немного дальше. Если я использую это в своей команде:
public function handle()
{
throw new \Exception("test exception");
}
и я выдаю команду php artisan -v dp:test
, печатается ошибка. Трассировка только не печатается, когда исключение выбрасывается из-за ошибки PHP. В методе Illuminate/Foundation/Bootstrap/HandleExceptions.php
bootstrap
Ошибки PHP преобразуются в Исключения. Когда это происходит, генерируется исключение, но при печати значение -v каким-то образом игнорируется. Это очень неудобно, потому что он сильно затрудняет отладку приложений CLI.
Я думаю, что решение можно найти в vendor/symfony/console/Application.php
, method renderException
.
Я собираюсь копать дальше позже, если кто-то другой не сможет указать решение быстрее меня: -)
Ответы
Ответ 1
Я нашел причину, по которой -v игнорируется:
в Illuminate/Foundation/Bootstrap/HandleExceptions.php
, метод renderForConsole
создает объект ConsoleOutput
с настройками по умолчанию, не принимая во внимание параметры подробностей, заданные пользователем:
protected function renderForConsole($e)
{
$this->getExceptionHandler()->renderForConsole(new ConsoleOutput, $e);
}
По этой причине любое значение -v -vv или -vvv установлено, $output->getVerbosity()
in vendor/symfony/console/Application.php
всегда меньше, чем OutputInterface::VERBOSITY_VERBOSE
, поэтому трассировка стека не печатается.
Вероятно, я начинаю проблему с github, потому что я думаю, что это намного удобнее, если ошибки отображаются в CLI, если пользователь устанавливает -v.
Ответ 2
Вы можете установить многословие на любой уровень, который вам нужен, добавив следующий оператор использования:
use Symfony\Component\Console\Output\OutputInterface;
И затем добавив это в начало вашей функции дескриптора:
$this->output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
См. документацию для консоли symfony здесь http://symfony.com/doc/current/console/verbosity.html
для получения дополнительной информации.
Ответ 3
Если вы посмотрите на класс Illuminate\Console\Command
, вы увидите определение функции, которая записывает строку ошибки в консоль:
/**
* Write a string as error output.
*
* @param string $string
* @return void
*/
public function error($string)
{
$this->output->writeln("<error>$string</error>");
}
Теперь, когда вы видите, что он записывает только строку ошибки, вы можете немного поиграть с ней, чтобы достичь того, чего хотите. Вы можете получить обратную трассировку функции и вывести столько строк и файлов, сколько хотите. Просто создайте класс, который расширяет команду, переопределяет функцию и заставляет все ваши команды наследовать этот класс команд:
/**
* Write a string as error output.
*
* @param string $string
* @return void
*/
public function error($string)
{
$this->output->writeln("<error>$string</error>");
$trace = debug_backtrace();
foreach ($trace as $t)
{
$this->output->writeln("Trace : " . $t['file'] . " on line " . $t['line'] . " function " . $t['function']);
}
}