I wanted to try creating a nicer output for ValidationException
so I could see which validation fields and messages were detected. It looked like overriding renderForConsole
would do what I wanted. However, the code I put in there never got called.
The code I was writing looked something like this:
I eventually found someone had already brought this up as an issue on laravel/framework#23515. I thought @thomasfw had a reasonable point and I am hoping to find a way around this. :)
We should be able to handle specific Exceptions when required, with all others being passed on to Collision's ExceptionHandler to be rendered nicely.
That is more or less what I expected to happen. It took me quite some time to figure out why it wasn't working like this. I tracked it down to this part of the code:
https://github.com/nunomaduro/collision/blob/stable/src/Adapters/Laravel/ExceptionHandler.php#L74-L88
Honestly, I think it will be technically difficult to solve. But I'm happy to help however I can as I'm sure it can be solved. :)
The only easy way I found to do this without hacking framework or collision itself was the following, which I'm not super happy with, but better than nothing?
namespace App\Console;
class Kernel extends ConsoleKernel
{
protected function renderException($output, Exception $e)
{
if ($this->renderValidationException($output, $e)) {
return;
}
parent::renderException($output, $e);
}
protected function renderValidationException($output, Exception $e): bool
{
if (! $e instanceof ValidationException) {
return false;
}
// send validation messages to $output
return true;
}
}
What I think is more likely possible is to not break after a handler does its work. For example, the following would always execute collision even if a validation exception is thrown:
namespace App\Console;
class Kernel extends ConsoleKernel
{
protected function renderException($output, Exception $e)
{
$this->renderValidationException($output, $e);
parent::renderException($output, $e);
}
protected function renderValidationException($output, Exception $e): bool
{
if (! $e instanceof ValidationException) {
return;
}
// send validation messages to $output
}
}
... to implement that, I think it would look something like this:
/**
* {@inheritdoc}
*/
public function renderForConsole($output, Exception $e)
{
if ($e instanceof SymfonyConsoleExceptionInterface) {
$this->appExceptionHandler->renderForConsole($output, $e);
} else {
// always give the app exception handler a crack at it...
$this->appExceptionHandler->renderForConsole($output, $e);
$handler = $this->container->make(ProviderContract::class)
->register()
->getHandler()
->setOutput($output);
$handler->setInspector((new Inspector($e)));
$handler->handle();
}
}
Unfortunately, I'm not certain this wouldn't end up in some sort of infinite recursion.
Anyway, this is as far as I've come so far. :) If this is something I can help with, let me know! Would love to have an officially supported solution instead of what I have hacked together.