【问题标题】:How can I make Laravel return a custom error for a JSON REST API如何让 Laravel 返回 JSON REST API 的自定义错误
【发布时间】:2014-04-20 07:21:20
【问题描述】:

我正在开发某种 RESTful API。当发生一些错误时,我会抛出一个App::abort($code, $message) 错误。

问题是:我希望他抛出一个带有键“代码”和“消息”的 json 格式的数组,每个都包含上述数据。

Array
(
    [code] => 401
    [message] => "Invalid User"
)

有谁知道这是否可行,如果可行,我该怎么做?

【问题讨论】:

    标签: php json rest laravel-4 restful-architecture


    【解决方案1】:

    您可以将数组传递给返回的 JSON 响应:

    $returnData = array(
        'status' => 'error',
        'message' => 'An error occurred!'
    );
    return Response::json($returnData, 500);
    

    【讨论】:

    • 谢谢!在 laravel 5 中它将是: return response()->json($returnData, 500)
    • 如果减少 $returnData 数组的使用,也可以变得更容易
    【解决方案2】:

    转到您的app/start/global.php

    这会将 401404 的所有错误转换为自定义 json 错误,而不是 Whoops 堆栈跟踪。添加这个:

    App::error(function(Exception $exception, $code)
    {
        Log::error($exception);
    
        $message = $exception->getMessage();
    
        // switch statements provided in case you need to add
        // additional logic for specific error code.
        switch ($code) {
            case 401:
                return Response::json(array(
                        'code'      =>  401,
                        'message'   =>  $message
                    ), 401);
            case 404:
                $message            = (!$message ? $message = 'the requested resource was not found' : $message);
                return Response::json(array(
                        'code'      =>  404,
                        'message'   =>  $message
                    ), 404);        
        }
    
    });
    

    这是处理此错误的众多选项之一。


    制作 API 最好创建自己的帮助程序,例如扩展 Response 类的 Responser::error(400, 'damn')

    有点像:

    public static function error($code = 400, $message = null)
    {
        // check if $message is object and transforms it into an array
        if (is_object($message)) { $message = $message->toArray(); }
    
        switch ($code) {
            default:
                $code_message = 'error_occured';
                break;
        }
    
        $data = array(
                'code'      => $code,
                'message'   => $code_message,
                'data'      => $message
            );
    
        // return an error
        return Response::json($data, $code);
    }
    

    【讨论】:

    • 我真的很喜欢你说的第二件事。关于API,虽然我并不完全理解。我是否应该创建另一个类,在其中扩展 Response 类并调用它而不是“正确的”类?就这样?
    • @DennisBraga 是对的。它可以帮助您在 API 中保持统一的错误响应。
    【解决方案3】:

    这是我使用的(Laravel 5.2):

    根据:https://laravel.com/docs/5.2/errors,我们可以为app\Exceptions\Handler.php中的错误指定自定义渲染函数。我所做的只是将我的渲染函数更改为:

        /**
         * Render an exception into an HTTP response.
         * Updated to return json for a request that wantsJson 
         * i.e: specifies 
         *      Accept: application/json
         * in its header
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Exception  $e
         * @return \Illuminate\Http\Response
         */
        public function render($request, Exception $e)
        {
            if ($request->ajax() || $request->wantsJson()) {
                return response()->json(
                              $this->getJsonMessage($e), 
                              $this->getExceptionHTTPStatusCode($e)
                            );
            }
            return parent::render($request, $e);
        }
    
        protected function getJsonMessage($e){
            // You may add in the code, but it's duplication
            return [
                      'status' => 'false',
                      'message' => $e->getMessage()
                   ];
        }
    
        protected function getExceptionHTTPStatusCode($e){
            // Not all Exceptions have a http status code
            // We will give Error 500 if none found
            return method_exists($e, 'getStatusCode') ? 
                             $e->getStatusCode() : 500;
        }
    

    在此之后,您需要做的就是确保所有 API 请求都指定 Accept: application/json 标头。希望这会有所帮助:)

    【讨论】:

    • 你是国王!只需一个很小的 ​​sn-p 我就可以处理 ajax 响应。凉爽的。示例:中止(401,'未授权');
    【解决方案4】:

    根据 Ibrahim 的回答,并非每个 ajax 请求都需要 JSON,响应“状态代码”“状态”是不必要的,因为它们的含义相同。更重要的是,根本不需要在响应“状态”中提及,因为响应代码“说”了这一点。这样的东西应该可以完美运行:

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $e
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $e)
    {
        if ($request->wantsJson())
            return response()->json(
                ['message' => $e->getMessage()],
                method_exists($e, 'getStatusCode') ? $e->getStatusCode() : 500);
    
        return parent::render($request, $e);
    }
    

    【讨论】:

      【解决方案5】:

      这是我在 5.6 中使用的,以便返回与内置 validate 方法相同类型的响应:

      response()->json(['errors' => ['email' => ['The email is invalid.']]], 422);

      【讨论】:

        【解决方案6】:

        在 Laravel5.6 中,我通常为 app\Exceptions\Handler.php 中的错误指定自定义渲染函数。我所做的只是将我的渲染函数更改为:

        /**
         * Render an exception into an HTTP response.
         *
         * @param \Illuminate\Http\Request $request
         * @param \Exception               $e
         *
         * @return Response
         */
        public function render($request, Exception $e)
        {
            if ($request->wantsJson() && !($e instanceof ValidationException)) {
                $response = [
                    'message' => (string)$e->getMessage(),
                    'status_code' => 400,
                ];
        
                if ($e instanceof HttpException) {
                    $response['message'] = Response::$statusTexts[$e->getStatusCode()];
                    $response['status_code'] = $e->getStatusCode();
                } else if ($e instanceof ModelNotFoundException) {
                    $response['message'] = Response::$statusTexts[Response::HTTP_NOT_FOUND];
                    $response['status_code'] = Response::HTTP_NOT_FOUND;
                }
        
                if ($this->isDebugMode()) {
                    $response['debug'] = [
                        'exception' => get_class($e),
                        'trace' => $e->getTrace()
                    ];
                }
        
                return response()->json([
                    'status'      => 'failed',
                    'status_code' => $response['status_code'],
                    'massage'     => $response['message'],
                ], $response['status_code']);
            }
        
            return parent::render($request, $e);
        }
        

        【讨论】:

        • 那个答案看起来非常好,但遗憾的是它对我不起作用,Laravel 仍然给我 ```status "error" message "An error occurred."```` 作为响应 :(
        【解决方案7】:

        Laravel 6:

        您必须在客户端的 API 请求中设置 Accept:application/json 标头,Laravel 会自动返回 JSON 格式错误。

         {     
            "message": "Unauthenticated."
         }
        

        【讨论】:

          【解决方案8】:
          $response['message'] ="The given data was invalid";
          $error['country_id'] = ["The country field is required"];
          $error['state_id'] = ["The state field is required"];
          $error['name'] = ["The name field is required"];
          $response['error'] = $error;
          return response()->json($response,422);
          

          【讨论】:

            【解决方案9】:

            对于 Laravel 8

            转到您的 \app\Exceptions\Handler.php 并像这样覆盖 invalidJson 方法:

            // Add this line at the top of the class
            use Illuminate\Validation\ValidationException;
            
            
            /**
             * Convert a validation exception into a JSON response.
             *
             * @param  \Illuminate\Http\Request  $request
             * @param  \Illuminate\Validation\ValidationException  $exception
             * @return \Illuminate\Http\JsonResponse
             */
            protected function invalidJson($request, ValidationException $exception)
            {
                // You can return json response with your custom form
                return response()->json([
                    'success' => false,
                    'data' => [
                        'code' => $exception->status,
                        'message' => $exception->getMessage(),
                        'errors' => $exception->errors()
                    ]
                ], $exception->status);
            }
            

            响应样本:

            {
              "success": false,
              "data": {
                "code": 422,
                "message": "The given data was invalid.",
                "errors": {
                  "password": [
                    "The password field is required."
                  ]
                }
              }
            }
            

            原来的方法是:

            /**
             * Convert a validation exception into a JSON response.
             *
             * @param  \Illuminate\Http\Request  $request
             * @param  \Illuminate\Validation\ValidationException  $exception
             * @return \Illuminate\Http\JsonResponse
             */
            protected function invalidJson($request, ValidationException $exception)
            {
                return response()->json([
                    'message' => $exception->getMessage(),
                    'errors' => $exception->errors(),
                ], $exception->status);
            }
            

            响应样本:

            {
              "message": "The given data was invalid.",
              "errors": {
                "password": [
                  "The password field is required."
                ]
              }
            }
            

            请注意,unauthenticated 响应是在单独的方法中,因此您也可以覆盖它

            /**
             * Convert an authentication exception into a response.
             *
             * @param  \Illuminate\Http\Request  $request
             * @param  \Illuminate\Auth\AuthenticationException  $exception
             * @return \Symfony\Component\HttpFoundation\Response
             */
            protected function unauthenticated($request, AuthenticationException $exception)
            {
                return $request->expectsJson()
                    // Here you can change the form of the json response
                    ? response()->json(['message' => $exception->getMessage()], 401) // <-
                    : redirect()->guest($exception->redirectTo() ?? route('login'));
            }
            

            【讨论】:

            • invalidJson() 在 laravel 8 的 \app\Exceptions\Handler.php 中不存在。
            • \app\Exceptions\Handler.php extends Illuminate\Foundation\Exceptions\Handler, invalidJson() 存在于父类中,你只需要重写它来改变它的行为
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-04-11
            • 2015-12-26
            • 1970-01-01
            • 1970-01-01
            • 2021-10-15
            • 2016-05-03
            相关资源
            最近更新 更多