3

I have a Laravel 4.2 application with the following route:

Route::group(['prefix' => 'api/v1'], function()
{
    Route::resource('service_logs', 'ServiceLogsController', [
        'only' => ['index', 'store', 'show']
    ]);
});

The ServiceLogsController controller extends from ApiController, which looks something like this cut down version:

class ApiController extends \BaseController {

    protected $statusCode = 200;

    public function getStatusCode()
    {
        return $this->statusCode;
    }

    public function setStatusCode($statusCode)
    {
        $this->statusCode = $statusCode;

        return $this;
    }

    public function respondInternalError($message = 'Internal Error!')
    {
        return $this->setStatusCode(500)->respondWithError($message);
    }

    public function respondWithError($message)
    {
        return Response::json([
            'error' => [
                'message' => $message,
                'status_code' => $this->getStatusCode()
            ]
        ], $this->getStatusCode());
    }

    // ...

}

What I'd like to do is, when ever an un-caught exception occurs, I want to call the respondInternalError() method on my ApiController, so that the API consumer has a consistent response rather than nothing or html whoops error.

To achieve this, I tried adding the following code in my app/start/global.php

App::error(function(Exception $exception, $code)
{
    Log::error($exception);

    if (Request::is('api/*'))
    {
        App::make('ApiController')->respondInternalError('Uncaught api exception error occurred - ' . $exception->getMessage());
    }
});

and to test it, I tried to make a POST request to the following url: /api/v1/service_logs/123.

this will not work, because that URL is a GET url, so Laravel throws the correct method not allowed exception. However, it's not getting caught.

Any idea how to implement a catch all exception handler per controller class basis?


Update Slightly improved working "global" api exception handler

App::error(function(Exception $exception, $code)
{
    Log::error($exception);

    if (Request::is('api/*'))
    {
        $errorName = Symfony\Component\HttpFoundation\Response::$statusTexts[$code];

        return App::make('ApiController')
            ->setStatusCode($code)
            ->respondWithError($errorName . ' error has occurred.');
    }
});

When an error occurs, you get this now (testing done in Chrome + Postman):

enter image description here

3
  • The call of Request::is() in a static manner returns an exception in my setting... Commented Dec 19, 2014 at 15:08
  • I tried calling App::make('ApiController')->respondInternalError() directly without checking request to see if my method was at-least getting called, it wasn't. Commented Dec 19, 2014 at 17:23
  • For those in Laravel 5 this may help you make this work. stackoverflow.com/questions/26630985/… Commented Jun 10, 2015 at 22:41

1 Answer 1

1

The solution is actually very very simple. You only need to return the return value of your controller function

if (Request::is('api/*'))
{
    return App::make('ApiController')->respondInternalError('Uncaught api exception error occurred - ' . $exception->getMessage());
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.