Within PHP / Laravel MVC applications response codes and bodies are often dictated by the Exception that is thrown. If a HTTP exception is thrown (inheriting from Symfony\Component\HttpKernel\Exception\HttpException
) the correct response codes are thrown (and in certain cases JSON responses). There are other types of exceptions that are non-http related as well that can be thrown.
Where should HTTP exceptions be thrown?
Should I be catching my exceptions in the controller and throwing HTTP versions of those exceptions? Or should I just throw a HTTP exception anywhere deep within a service class, repository or utility considering 99% of MVC framework apps are based around a HTTP request >> response lifecycle anyway?
Through your config/app. php , set 'debug' => env('APP_DEBUG', false), to true . Or in a better way, check out your . env file and make sure to set the debug element to true.
You need to create blade views for error pages, move to this path resources/views/ inside here create errors folder and within the directory create 404. blade. php file. It will redirect you to the 404 page if you don't find the associated URL.
Where should HTTP exceptions be thrown?
While this is generally up to preference, the framework itself seems to have taken an opinionated stance on this and it is that you should be throwing them anywhere. In fact Laravel has a few useful helpers to make throwing exceptions with associated response codes easier:
abort(403, "Exception message"); //Will throw an HTTP exception with code 403
abort_if(true, 400, "Condition failed"); //Will throw a 400 error if the first parameter is true
abort_unless(false, 422, "Condition failed"); //Will throw a 422 error if the first parameter is false
Practical example:
public function getById($id) {
$model = Model::find($id);
//These are equivalent
if ($model == null) {
abort(404, "$id not found");
}
abort_if($model == null, 404, "$id not found");
abort_unless($model != null, 404, "$id not found");
}
This is touched upon in the Error handling section of the manual
Note that abort
does raise HTTP exceptions so you can still catch them and handle them if you need to.
There seems to be a general misunderstanding regarding this question. It was my understanding that the question was where HTTP exceptions should be thrown but it's evolving to a more generic exception handling in the context of HTTP.
First of all, if you have an HTTP exception, meaning an exception that only makes sense in the context of an HTTP request/response cycle, then you should be able to throw it where it occurs and not throw something else with the purpose of converting it when it reaches the controller, this is what the abort
helpers are there to do.
However if you have an exception (any kind of exception) that should be interpreted with a specific http response code when left unhandled you have options to deal with that:
HttpException
(This might feel a bit strange that a perfectly normal exception inherits from a class that doesn't make sense outside the request/response lifecycle).Implement the render
method within your exception e.g.:
class SpecialException extends Exception {
public function render() {
return response()->view('errors.403', [], 403);
}
}
Have a specific handling behaviour within your \App\Exceptions\Handler for example:
class Handler {
// ....
public function render($request, $exception) {
if ($exception instanceof SpecialException) {
return response()->view('errors.403', [], 403);
}
return parent::render()
}
}
My answer is not targeted at Laravel as I feel working with a framework mindset actually goes against your initial question.
Always throw a tailored exception and then handle the conversion within the controller. In this case wrap it in a HttpException
. There are a few good reasons for this:
HttpException
throws in your service make no sense to your CLI command.Essentially thinking about a calculator, it would throw a DivisionByZeroException
. For a controller you would wrap this in a HttpException
400 BAD REQUEST
and re-throw. For the CLI your command could just let the exception render on screen Division By Zero
. Either way this decision is not made by your service.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With