I’m trying to modify my AppExceptionsHandler
to pass the request (and therefore current URL) through to all exceptions. For this reason I need the lowest-level exception class I can get hold of to type-hint to the ->renderable()
method.
Laravel/Symfony’s HttpException
works but only for HTTP errors, leaving out all non-HTTP exceptions. PHP’s Exception
class works when using getCode()
instead of getStatusCode()
, but always returns a "0" for both HTTP errors and exceptions. Is there another low-level exception class that will work for my purposes, or otherwise any other way to accomplish what I’m trying to do here?
public function register()
{
$this->renderable(function (Exception $exception, $request) {
$url = $request->fullUrl();
$status = $exception->getCode();
Log::warning("Error $status when trying to visit $url. Received the following message: " . $exception->getMessage());
return response()->view("errors.$status", [
"exception" => $exception
],
$status
);
});
}
}
For what it’s worth, I’m using the following web routes to trigger exceptions and HTTP errors for testing:
if (app()->environment('local')) {
Route::get("/exception", function (){
throw new JsonException; // chosen because it's one of the few Laravel exceptions
// that doesn't seem to automatically resolve to a HTTP error
});
}
if (app()->environment('local')) {
Route::get("/fail/{status}", function ($status){
abort($status);
});
}
3
Answers
I finally managed to figure this out in the end. It's probably not the cleanest solution, but it works perfectly for my needs.
It works by inspecting each instance of the Exception class and using PHP's
instanceof()
to check whether it's a HTTP exception or not. If it is, it gets logged with the request URL and returns a view with a status code. If it's a generic non-HTTP exception, it gets logged with the request URL and returns another view with no status code (or you can keep the default exception behaviour by removing the return block, which renders a blank screen in production).You can throw your JsonException and abort like so with a given code and the handler should grab it from
getCode
like soThat said it’s better to keep them as semantically separate as possible in my opinion, and let the handler do the handling depending on what it receives.
As requested, this is what I have in my Handler. I use some custom logging, and I want to make sure I grab the right code when it’s an HTTP error.
You can use
$e->getCode()
for your default as well