Laravel Dingo Api - 如何从API控制器返回JSON格式的错误响应?

时间:2014-07-03 17:55:51

标签: php laravel

在我的routes.php中,我有这个:

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

受保护的场地API路由访问控制器方法。控制器方法在Venues模型上执行Eloquent Query,并返回响应。这非常有效。 问题在于,如果我想返回错误 - 我不确定如何。这是场地方法:

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;

}

我尝试过的解决方案(在try块中):

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

当我尝试这样做时,我收到以下错误: 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

第二次尝试的解决方案: 从Dingo的返回错误,文档,我测试了如果我返回一个例外会发生什么:

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

但是,不会将错误作为JSON响应返回,而是会出现laravel错误页面,并显示以下错误:

[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 个答案:

答案 0 :(得分:2)

从Dingo的Returning Errors文档中读到,它说:

  

不是手动创建和返回错误响应,而是简单地抛出异常,包将处理异常并返回适当的响应。

     

以下是遇到错误时应该抛出的所有支持异常的列表。

     

的Symfony \元器件\ HttpKernel \异常\ AccessDeniedHttpException   Symfony的\分量\ HttpKernel \异常\ BadRequestHttpException   Symfony的\分量\ HttpKernel \异常\ ConflictHttpException   Symfony的\分量\ HttpKernel \异常\ GoneHttpException   Symfony的\分量\ HttpKernel \异常\ HttpException   Symfony的\分量\ HttpKernel \异常\ LengthRequiredHttpException   Symfony的\分量\ HttpKernel \异常\ MethodNotAllowedHttpException   Symfony的\分量\ HttpKernel \异常\ NotAcceptableHttpException   Symfony的\分量\ HttpKernel \异常\ NotFoundHttpException   Symfony的\分量\ HttpKernel \异常\ PreconditionFailedHttpException   Symfony的\分量\ HttpKernel \异常\ PreconditionRequiredHttpException   Symfony的\分量\ HttpKernel \异常\ ServiceUnavailableHttpException   Symfony的\分量\ HttpKernel \异常\ TooManyRequestsHttpException   Symfony的\分量\ HttpKernel \异常\ UnauthorizedHttpException   的Symfony \组件\ HttpKernel \异常\ UnsupportedMediaTypeHttpException

它还支持一些可以传递验证错误的通用资源异常:

  

野狗\阿比\异常\ DeleteResourceFailedException   巴丁格\阿比\异常\ ResourceException   巴丁格\阿比\异常\ StoreResourceFailedException   野狗\阿比\异常\ UpdateResourceFailedException

所以简而言之,你需要抛出上面的一个例外,Dingo支持回到Dingo。例如:

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

或者实际上,如果抛出的异常是上面的类型之一,或者扩展它们的异常,你可以完全删除你的try / catch子句。该异常应自动返回到Dingo来处理它。

答案 1 :(得分:2)

在构建api时,您可以在全局范围内捕获类似的异常类型。例如,如果用户试图获得一个不存在ID的客户,那么您可以这样做。

Customer::findOrFail($id);

然后你可以像app/start/global.php那样在App::error(function(ModelNotFoundException $modelNotFoundException){ $errorResponse = [ 'errors' => 'Not found any resource', 'message' => $modelNotFoundException->getMessage() ]; return Response::json($errorResponse, 404); //404 = Not found }); 中捕获所有这种类型的异常。

{{1}}

答案 2 :(得分:0)

请检查以下内容:

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

请检查并告知我。