If you're building a Laravel project with both Web and API sides, you need to customize error messages for each of them separately. In web-view there should be error pages, and API exceptions should return JSON with status codes. How to handle it? I will show you an example with case of Model Not Found 404.
Imagine this scenario - a web page user profile, and API-based similar request.
So, we have app/Http/Controllers/UserController.php:
public function show(User $user)
{
return view('users.show', compact('user'));
}
And then we have API - in app/Http/Controllers/API/V1/UserController.php:
public function show(User $user)
{
return $user;
}
The second example will just return JSON'ed Collection, without any web template. And that's fine.
The problem starts when you try to load that API call and the user is not found. Since we're using Route Model Binding here and passing (User $user) directly, under the hood it's launching User::findOrFail($id) method and throws exception of ModelNotFoundException and shows 404 page.
In API side, you also get an error page instead of JSON error:
So, our goal is to stay as it is for the web version, but override the API error handling to return a proper JSON.
To do that, we need to add this logic to the app/Exceptions/Handler.php class:
use Illuminate\Database\Eloquent\ModelNotFoundException;
// ...
public function render($request, Exception $exception)
{
if ($exception instanceof ModelNotFoundException && $request->wantsJson()) {
return response()->json(['message' => 'Not Found!'], 404);
}
return parent::render($request, $exception);
}
And that's it, you will receive a well-formed response in Postman:
And it won't change the default behavior for web-based requests, it will still show good old 404 page.
For more tips how to handle API errors and exceptions, see my other in-depth article.
In laravel 10+ using Throwable and $exception => $e may be good
public function render($request, \Exception|Throwable $e) { if ($e instanceof ModelNotFoundException && $request->wantsJson()) { return response()->json(['message' => 'Not Found!'], 404); }
But anyway I am not sure is this still working or my project is messed up?
well I got the solution
In the doc
just update the register. Don't forget to add
sorry for the bad styling on question. Forgot to add apostrophe
Hi, yes, the solution from the docs seems like the right one. Thanks for the comment!