【问题标题】:Send custom response from validator in Laravel从 Laravel 中的验证器发送自定义响应
【发布时间】:2018-08-26 07:28:47
【问题描述】:

我有一个注册用户路由,它采用nameemailpassword。如果数据正确,即存在唯一的电子邮件和参数,它工作得非常好,但如果用户已经注册,那么 Laravel 会以自己的格式发送自动错误消息。我希望返回格式在成功或失败的情况下保持一致。

注册成功返回数据:

{
    "status": "success",
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjUsImlzcyI6Imh0dHA6Ly8xMjcuMC4wLjE6ODAwMC9hcGkvYXV0aC9yZWdpc3RlciIsImlhdCI6MTUyMTI3NTc5MiwiZXhwIjoxNTIxMjc5MzkyLCJuYmYiOjE1MjEyNzU3OTIsImp0aSI6Ik1wSzJSYmZYU1dobU5UR0gifQ.fdajaDooBTwP-GRlFmAu1gtC7_3U4ygD1TSBIqdPHf0"
}

但如果出现错误,它会以其他格式发送数据。

{"message":"The given data was invalid.","errors":{"email":["The email has already been taken."]}}

我希望它们保持一致。成功返回数据很好。但是如果发生故障,我想自定义数据。像这样的:

{"status":"error","message":"The given data was invalid.","errors":{"email":["The email has already been taken."]}}

基本上,我需要status 参数来提供每个响应。

另外,我在使用 Postman 时有一个查询,当发生错误时,输出是纯 HTML,HTML 页面是默认的 Laravel 页面,另一方面,当 Angular 发送相同的请求时,错误是我刚刚粘贴在上面的 json 格式。 由于 Angular 在任何情况下都得到 JSON 响应,这对我来说很好。但是为什么邮递员没有向我显示那个回复。

注册控制器:

public function register(RegisterRequest $request)
    {
        $newUser = $this->user->create([
            'name' => $request->get('name'),
            'email' => $request->get('email'),
            'password' => bcrypt($request->get('password'))
        ]);
        if (!$newUser) {
            return response()->json(['status'=>'error','message'=>'failed_to_create_new_user'], 500);
        }

        return response()->json([
            'status' => 'success',
            'token' => $this->jwtauth->fromUser($newUser)
        ]);
    }

注册请求处理程序:

 public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required',
            'email' => 'required | email | unique:users,email',
            'password' => 'required'
        ];
    }

【问题讨论】:

    标签: php laravel laravel-5 laravel-5.2 laravel-5.3


    【解决方案1】:

    如果我对您的理解正确,您总是会得到没有“状态”键的错误响应。

    你当前的代码会发生什么,有几件事:

    • RegisterController@register(RegisterRequest $request) 被路由调用
    • Laravel 看到你使用 RegisterRequest 类作为参数,并会为你实例化这个类。
    • 实例化这个类意味着它将直接验证规则。
    • 如果不符合规则,laravel 会直接响应发现的错误。
    • 此响应将始终在 laravel 的默认“布局”中,代码​​停在那里。

    结论:当你的验证规则不满足时,你的代码甚至不会被触发。

    我已经研究了一个解决方案并想出了这个:

    public function register(Illuminate\Http\Request $request)
    {
        //Define your validation rules here.
        $rules = [
            'name' => 'required',
            'email' => 'required | email | unique:users,email',
            'password' => 'required'
        ];
        //Create a validator, unlike $this->validate(), this does not automatically redirect on failure, leaving the final control to you :)
        $validated = Illuminate\Support\Facades\Validator::make($request->all(), $rules);
    
        //Check if the validation failed, return your custom formatted code here.
        if($validated->fails())
        {
            return response()->json(['status' => 'error', 'messages' => 'The given data was invalid.', 'errors' => $validated->errors()]);
        }
    
        //If not failed, the code will reach here
        $newUser = $this->user->create([
            'name' => $request->get('name'),
            'email' => $request->get('email'),
            'password' => bcrypt($request->get('password'))
        ]);
        //This would be your own error response, not linked to validation
        if (!$newUser) {
            return response()->json(['status'=>'error','message'=>'failed_to_create_new_user'], 500);
        }
    
        //All went well
        return response()->json([
            'status' => 'success',
            'token' => $this->jwtauth->fromUser($newUser)
        ]);
    }
    

    现在,不符合您的验证规则仍然会触发错误,但是您的错误,而不是 laravel 的内置错误 :)

    希望对你有帮助!

    【讨论】:

      【解决方案2】:

      这是我想出的:

      function validate(array $rules)
      {
          $validator = Validator::make(request()->all(), $rules);
          $errors = (new \Illuminate\Validation\ValidationException($validator))->errors();
          if ($validator->fails()) {
              throw new \Illuminate\Http\Exceptions\HttpResponseException(response()->json(
                  [
                      'status'     => false,
                      'message'    => "Some fields are missing!",
                      'error_code' => 1,
                      'errors'     => $errors,
                  ], \Illuminate\Http\JsonResponse::HTTP_UNPROCESSABLE_ENTITY));
          }
      }
      

      创建一个帮助目录 (App\Helpers) 并将其添加到一个文件中。不要忘记将它添加到您的 composer.json 中

      "autoload": {
          "files": [
              "app/Helpers/system.php",
          ],
      },
      

      现在您可以在控制器中调用validate() 并获得您想要的:

      validate([
          'email'    => 'required|email',
          'password' => 'required|min:6|max:32',
          'remember' => 'nullable|boolean',
          'captcha'  => 'prod_required|hcaptcha',
      ]);
      

      【讨论】:

        【解决方案3】:

        在 Laravel 8 中,我添加了我的自定义 invalidJson 和 "success": false:

        在 app/Exceptions/Handler.php 中:

        /**
         * 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([
                'success' => false,
                'message' => $exception->getMessage(),
                'errors' => $exception->errors(),
            ], $exception->status);
        }
        

        【讨论】:

          猜你喜欢
          • 2018-06-17
          • 2019-05-01
          • 2016-05-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-07-09
          • 2019-10-07
          相关资源
          最近更新 更多