php - How would you handle different error responses for different routes using Laravel

587

I have Laravel routes set up as the example below shows:

Route::group(array('domain' => 'example.com'), function()
{
    Route::get('/', array('as' => 'root.index', 'uses' => '[email protected]'));
    [...]
});

Route::group(array('domain' => 'api.example.com'), function()
{
    Route::when('*', 'ApiFilter');
    Route::get('/', array('as' => 'api.index', 'uses' => '[email protected]'));
    [...]
});

Now, when it comes to responding to requests with errors (such as 404, 403, 500 etc) Laravel provides a great solution usingApp::error and its related methods.

I would like to respond to errors differently depending on whether the request is for the root or api domain.

Can I do this usingApp::error?

Hope that makes sense.

Thanks

375

Answer

Solution:

Yes, you can do this. Just need to get the request object from the$exception object in the exception handler, for example, if you have an exception handler like this:

App::error(function(Exception $exception, $code)
{
    $request = $exception->getTrace()[0]['args'][0];
    $path = $request->path(); // will return path without domain, i.e. user/1
    // Take some action depending on the $path
});

Now depending on the path you may take an action. You may use any public method ofRequest class, such asif($request->is('admin/*')) or$request->url() to get full url with domain.

954

Answer

Solution:

You could also use content negotiation (Accept request header or URLs suffixed by.json /.xml) for different error formatting, like so:

App::error(function(Exception $exception, $code)
{
    if (!preg_match("@text/[email protected]", Request::header('Accept')))
    {
        return Response::json
        (
            array("error" => array("message" => $exception->getMessage())),
            $code
        );
    }
});

This would result in errors being returned as JSON, if request headerAccept would not containtext/html.

So.. if you would go to api.yoursite.com with your browser - you would still see the default HTML error page with stack-trace and full details, because browser will sendAccept: text/html.

Otherwise, ifAccept header is not set or does not explicitly containtext/html - error will be formatted as JSON.

Alternatively, instead ofpreg_match you could useRequest::wantsJson() for detecting requested content format.

Or if you absolutely need/want to separate API logics and go via sub-domain route..:

App::error(function(Exception $exception, $code)
{
    if (preg_match("@^https?://api\[email protected]", Request::url())) /* Or, if not using sub-domain: Request:is("api/*") */
    {
        return Response::json
        (
            array("error" => array("message" => $exception->getMessage())),
            $code
        );
    }
});
377

Answer

Solution:

I would apply separate filters to each route group, then specify error handling events in each filter.

People are also looking for solutions to the problem: php - Can we use { to declare e variable variable?

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.