1
votes

In my routes.php, I have this:

$apiSettings = [
    'version' => 'v1',
    'prefix' => 'api',
    'protected' => true
];   
Route::api($apiSettings, function() {
    Route::get('venue', 'ApiDataController@venue');
});

The protected venue API route accesses a controller method. The controller method performs the Eloquent Query on a Venues model, and returns the response. This works perfectly. The issue is in if I want to return an error - I am unsure how to. Here is the Venue Method:

public function venue(){

    try {
        //Some code that returns an exception
    } catch(someexception $e) {
        //How do I return the exception such that Dingo will parse it into a proper JSON response?
    }
    $response = Venue::with('address')->get();
    return $response;

}

My attempted solution (in the try block):

try {
    //some code that returns an exception
} catch(someexception $e) {
    $response = array(
        'message' => 'some random exception message'
    );
    return Response::json($response, 403);
}

I got the following error when I attempted to do that: Argument 1 passed to Dingo\Api\Http\Response::makeFromExisting() must be an instance of Illuminate\Http\Response, instance of Illuminate\Http\JsonResponse given, called in /vagrant/www/planat-app/vendor/dingo/api/src/Routing/Router.php on line 165 and defined

Second Attempted Solution: From Dingo's Returning Errors, docs, I tested what would happen if I returned one of the exceptions:

public function venue(){
    throw new Symfony\Component\HttpKernel\Exception\ConflictHttpException('err);
}

However, instead of returning the error as a JSON response, a laravel error page comes up, with the following error displayed:

[internal function]: ApiDataController->venue()
#1 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(231):
call_user_func_array(Array, Array)
#2 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(93):
Illuminate\Routing\Controller->callAction('venue', Array)
#3 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(62):
Illuminate\Routing\ControllerDispatcher->call(Object(ApiDataController),
Object(Illuminate\Routing\Route), 'venue')
#4 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Routing/Router.php(930):
Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route),
Object(Dingo\Api\Http\InternalRequest), 'ApiDataControll...', 'venue')
#5 [internal function]: Illuminate\Routing\Router->Illuminate\Routing\{closure}()
#6 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Routing/Route.php(105):
call_user_func_array(Object(Closure), Array)
#7 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Routing/Router.php(996):
Illuminate\Routing\Route->run(Object(Dingo\Api\Http\InternalRequest))
#8 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Routing/Router.php(964):
Illuminate\Routing\Router->dispatchToRoute(Object(Dingo\Api\Http\InternalRequest))
#9 /vagrant/www/planat-app/vendor/dingo/api/src/Routing/Router.php(147):
Illuminate\Routing\Router->dispatch(Object(Dingo\Api\Http\InternalRequest))
#10 /vagrant/www/planat-app/vendor/dingo/api/src/Dispatcher.php(337): Dingo\Api\Routing\Router->dispatch(Object(Dingo\Api\Http\InternalRequest))
#11 /vagrant/www/planat-app/vendor/dingo/api/src/Dispatcher.php(278): Dingo\Api\Dispatcher->dispatch(Object(Dingo\Api\Http\InternalRequest))
#12 /vagrant/www/planat-app/vendor/dingo/api/src/Dispatcher.php(213): Dingo\Api\Dispatcher->queueRequest('get', 'venue', Array)
#13 /vagrant/www/planat-app/app/routes.php(51): Dingo\Api\Dispatcher->get('venue')
#14 [internal function]: {closure}()
#15 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Routing/Route.php(105):
call_user_func_array(Object(Closure), Array)
#16 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Routing/Router.php(996):
Illuminate\Routing\Route->run(Object(Illuminate\Http\Request))
#17 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Routing/Router.php(964):
Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#18 /vagrant/www/planat-app/vendor/dingo/api/src/Routing/Router.php(147):
Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#19 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(738):
Dingo\Api\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#20 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(708):
Illuminate\Foundation\Application->dispatch(Object(Illuminate\Http\Request))
#21 /vagrant/www/planat-app/vendor/dingo/api/src/Http/Middleware/RateLimit.php(97):
Illuminate\Foundation\Application->handle(Object(Illuminate\Http\Request),
1, true)
#22 /vagrant/www/planat-app/vendor/dingo/api/src/Http/Middleware/Authentication.php(102):
Dingo\Api\Http\Middleware\RateLimit->handle(Object(Illuminate\Http\Request),
1, true)
#23 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Session/Middleware.php(72):
Dingo\Api\Http\Middleware\Authentication->handle(Object(Illuminate\Http\Request),
1, true)
#24 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Cookie/Queue.php(47):
Illuminate\Session\Middleware->handle(Object(Illuminate\Http\Request),
1, true)
#25 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Cookie/Guard.php(51):
Illuminate\Cookie\Queue->handle(Object(Illuminate\Http\Request), 1,
true)
#26 /vagrant/www/planat-app/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23):
Illuminate\Cookie\Guard->handle(Object(Illuminate\Http\Request), 1,
true)
#27 /vagrant/www/planat-app/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(606):
Stack\StackedHttpKernel->handle(Object(Illuminate\Http\Request))
#28 /vagrant/www/planat-app/public/index.php(49): Illuminate\Foundation\Application->run()
3
In the laravel error page, does it show the same "Argument 1 passed to Dingo\Api\Http\Response::makeFromExisting() must be an instance of Illuminate\Http\Response" or what does it show? I think it should show a different error now A more copy-pastable error message should be the last chunk in your app/storage/logs/laravel.log too.Unnawut
I've updated the question with the stack trace from laravel.logMuserk
I think it has to do with syntax error. Can you check that your controller action has correct braces and everything? Or post your controller action code here.Unnawut
Would be nice too if you could get the error log two lines above [internal function]:Unnawut
@Unnawut why you need to try catch and then response exception message. Dingo Will handle exception and will response exception message automatically. See the following example. { "message": "Undefined variable: x", "status_code": 500 } Api endpoint have a undefined variable "x" and dingo handle it appropriatelyTuhin Bepari

3 Answers

3
votes

As you are building api, you can catch similar types of exception globally. For example, if a user tried to get a customer with an ID which doesn't exists, then you could do this.

Customer::findOrFail($id);

then you could catch all of this type exception in app/start/global.php like this.

App::error(function(ModelNotFoundException $modelNotFoundException){
    $errorResponse = [
        'errors'    => 'Not found any resource',
        'message'   => $modelNotFoundException->getMessage()
    ];

    return Response::json($errorResponse, 404);     //404 = Not found
});
2
votes

Reading from Dingo's Returning Errors docs, it says:

Instead of manually creating and returning an error response you can simply throw an exception and the package will handle the exception and return an appropriate response.

The following is a list of all the supported exceptions that you should throw when you encounter an error.

Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException Symfony\Component\HttpKernel\Exception\BadRequestHttpException Symfony\Component\HttpKernel\Exception\ConflictHttpException Symfony\Component\HttpKernel\Exception\GoneHttpException Symfony\Component\HttpKernel\Exception\HttpException Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException Symfony\Component\HttpKernel\Exception\NotFoundHttpException Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException

It also supports some generic resource exceptions that you can pass validation errors onto as well:

Dingo\Api\Exception\DeleteResourceFailedException Dingo\Api\Exception\ResourceException Dingo\Api\Exception\StoreResourceFailedException Dingo\Api\Exception\UpdateResourceFailedException

So in short, you need to throw one of the exceptions above that Dingo supports back to Dingo. For example:

try {
    //Some code that returns an exception
} catch(SomeException $e) {
    throw new Symfony\Component\HttpKernel\Exception\HttpException($e->getMessage);
}

Or in fact, if the exception thrown is one of the type above, or one that extends them, you can just remove your try/catch clause completely. The exception should be automatically thrown back to Dingo to handle it.

0
votes

Please check this:

try {
    //some code that returns an exception
} catch(\Exception $e) {
    $response = array(
        'message' => 'some random exception message'
    );
    return response()->json($response, 403);
}

Please check and let me know.