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");
abort_if(true, 400, "Condition failed");
abort_unless(false, 422, "Condition failed");
Practical example:
public function getById($id) {
$model = Model::find($id);
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:
- Make that exception inherit from the Symfony
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()
}
}