In Laravel 9, as per Official Documentation ModelNotFoundException
is directly forwarded to NotFoundHttpException
(which is a part of Symfony Component) that used by Laravel and will ultimately triggers a 404 HTTP response.
so, we need to checking Previous Exception using $e->getPrevious()
just check previous exception is instanceof ModelNotFoundException or not
see below my code
// app/Exceptions/Handler.php file
$this->renderable(function (NotFoundHttpException $e, $request) {
if ($request->is('api/*')) {
if ($e->getPrevious() instanceof ModelNotFoundException) {
/** @var ModelNotFoundException $modelNotFound */
$modelNotFound = $e->getPrevious();
if($modelNotFound->getModel() === Product::class) {
return response()->json([
'message' => 'Product not found.'
], 404);
}
}
return response()->json([
'message' => 'not found.'
], 404);
}
});
additionally,
In API Response, if you are getting view as a response instead of JSON during other HTTP responses like HTTP 422 (validation error), 500 Internal server error. because $request->wantsJson()
uses the Accept
header sent by the client to determine if it wants a JSON response. So you need to set 'Accept' header value as "application/json"
in request. see Validation Error Response
Method 1 :- set accept
value as a application/json
to every incoming api requests using middleware
JsonResponseApiMiddleware middleware created for set accept header to every incoming api requests
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class JsonResponseApiMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
// $acceptHeader = $request->header('Accept');
// set 'accept' header value as a json to all request.
$request->headers->set('accept', 'application/json', true);
return $next($request);
}
}
set JsonResponseApiMiddleware middleware class to api middlewareGroups
. for this open Kernel.php
file at App\Http directory
// App/Http/Kernel.php file
protected $middlewareGroups = [
// ...
'api' => [
// ... other middleware group
\App\Http\Middleware\JsonResponseApiMiddleware::class,
]
]
Method 2 :- set accept
value as a application/json
api requests only when any exception occurs, for this open Handler.php
file at App\Exceptions directory. credit about this method 2
// App/Exceptions/Handler.php file
$this->renderable(function (Throwable $e, $request) {
if($request->is('api/*') || $request->wantsJson()) {
// set Accept request header to application/json
$request->headers->set('Accept', 'application/json');
}
});