This can help you make your logic
https://laracasts.com/series/incremental-api-development/episodes/3
Custom Exception Handler Based on Route Group
I'm trying to find a way to use a specific exception handler in Laravel 5 for two different route groups. I want to display a page based error page for one route group then for my api routes I want to display the error in json. Any direction on how to accomplish this?
Sorry I don't think I was clear in my first explanation. I'm trying to customize the Exception Handler to return a JSON response for a certain Route group but want it to return a view (custom error page) for another Route group. One is an API and one is a page based group. So not looking to return errors in the controller through the Response facade but instead I'm looking to catch all errors and return them as JSON for the API route group and a view for the page based route group. Hopefully that makes sense.
@dannydinges in that case you can do something like this in your exceptions/handler.php file (Not tested, Not sure if it will work, but just a concept)
public function render($request, Exception $e)
{
if($request->has('your api group prefix ')){
// TODO convert the error to json format and return
}
return parent::render($request, $e);
}
I'm interested in doing the exact same thing. I would think this would also be necessary for distinguishing between web, AJAX and API calls, right?
Here's what I did, and this works, but I'm not sure if it's the best way to accomplish this.
Basically in my .env I have:
APP_URI=app.domain.com
API_URI=api.domain.com
Then in app/Exceptions/Handler.php:
public function render($request, Exception $e)
{
if($request->server->get('SERVER_NAME') == getenv('API_URI'))
{
if ($e instanceOf NotFoundHttpException)
{
return \Response::json(['error' => ['message' => 'API endpoint not found.', 'status_code' => 404]], 404);
}
}
return parent::render($request, $e);
}
we had similar request we did something like this which worked for us.
public function render($request, Exception $e)
{
if($request->is('api/*')){
return response()->json([
'error_message' => $e->getMessage(),
'status' => Response::HTTP_BAD_REQUEST
]);
}
return parent::render($request, $e);
}
Thanks for the workaround, unfortunately it doesn't suit my case. I required a custom Handler class for the route group because I'm building a Laravel package, so I can't modify the existing Handler to add this if statement.
And btw cactus's example needs
use Symfony\Component\HttpFoundation\Response;
I actually have a similar thread out at the moment (but with no replies!) but your thread spurred me to do some googling.
Any of these any help?
- http://stackoverflow.com/questions/19360215/how-to-bypass-laravel-exception-handling
- https://laracasts.com/discuss/channels/laravel/any-way-of-overriding-exception-handling-in-a-package-laravel-5
Right be a bit draconian in your case...
Thanks but neither of those helped. I have figured out my own solution, not sure if there are any issues with it.
In my api_routes.php created by InfyOm Laravel Generator (but you could just put it in your API route group) I put this:
$this->app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\APIHandler::class
);
I believe this switches the exception handling from the original Handler class to a new APIHandler. Then I created this APIHandler class in the Exceptions folder, and in the render method have it render to JSON as in the above snippet by cactus (without the if statement). My only worry is about exceptions that might happen before it gets to the routing stage, if there are any?
Sweet - think I might be able to use that as well!
Did you just dump the app instance and look for exception references?
No I looked through the config and bootstrap folders and found where it is originally set in bootstrap/app.php
Sorry my solution doesn't work because it turns out Route::group gets executed even if the URL path does not match. This means it isn't possible to change the exception handler depending on the route group.
Think I've solved this now, switch the handler in the controller constructor like this:
class RestApiController extends Controller
{
public function __construct()
{
\App::singleton(
\Illuminate\Contracts\Debug\ExceptionHandler::class,
RestApiHandler::class
);
}
@malhal not working on laravel 5.4, any idea?
We used malhal's solution (switching the ExceptionHandler singleton) except that we created a new middleware group, created a middleware that runs App::singleton to change the exception handler, and ordered that middleware first in the group. (So that exceptions in other middlewares run with the right handler.)
Please or to participate in this conversation.