Custom error pages in Laravel (for the same Exception)
Occasionally I can’t decide whether the question I’m asking about a piece of technology (in this case, Laravel) is so advanced as to no one understands it, or so simple that no one answers because they all assume I already know the answer. In either case, I didn’t get the answer to the following question:
I want to display a different template that’s dependent on the Model that’s not being found. I know I can create a
resources/views/errors/404.blade.php
template, but that would be used for ALL not founds. I want to use a different one if aModelA
isn’t found, and a different template ifModelB
isn’t found.
Attempts & Confusion
The obvious place to look is in Laravel’s documentation, which has a fairly simple page on Errors & Logging (5.4). In there there’s a section about The render method, which says the following:
The render method is responsible for converting a given exception into an HTTP response that should be sent back to the browser. By default, the exception is passed to the base class which generates a response for you. However, you are free to check the exception type or return your own custom response:
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
if ($exception instanceof CustomException) {
return response()->view('errors.custom', [], 500);
}
return parent::render($request, $exception);
}
That’s cool, Laravel, but my exception is not going to be of the type CustomException
, so this doesn’t help me much.
Further down there’s a section on HTTP Exceptions, and custom exception pages, but that talks about lumping ALL 404 errors into one template, which is specifically what I did not want to do.
Solution
In my frustration, after having tried unsuccessfully to get answers across two different Slack channels, I decided to just dd
the contents of $request
and $exception
passed to the render
method.
Turns out, all the data I needed was there. After following the exception classes up the chain and looking at available methods, this is the solution that I came up with:
public function render($request, Exception $exception)
{
if (
$exception instanceof ModelNotFoundException &&
'ModelA' === $exception->getModel() &&
view()->exists( 'errors.modela404' ) )
{
return response()->view( 'errors.modela404', [], 404 );
}
return parent::render($request, $exception);
}
Of course the file at resources/views/errors/modela404.blade.php
needs to exist :).