【问题标题】:How to throw a 404 in Laravel Form Request with custom Rule如何使用自定义规则在 Laravel 表单请求中抛出 404
【发布时间】:2021-01-02 01:21:26
【问题描述】:

通常 Laravel 的表单请求会在验证失败时返回一个通用的 400 代码,如下所示:

{
  "message": "The given data is invalid",
  "errors": {
    "person_id": [
      "A person with ID c6b853ec-b53e-4c35-b633-3b1c2f27869c does not exist"
    ]
  }
}

如果请求未通过我的自定义规则,我想返回 404。

我的自定义规则检查数据库中是否存在记录:

class ValidatePersonExists implements Rule
{
    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
    public function passes($attribute, $value)
    {
        return Person::where('id', $value)->exists();
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return "A person with ID :input does not exist";
    }
}

如果我在 exists() 检查失败时抛出 ModelNotFoundException,我在哪里可以捕捉到它以友好的 404 响应进行响应?

这是我使用规则的表单请求:

public function rules()
{
    return [
        'person_id' => ['bail', 'required', 'uuid', new ValidatePersonExists],
    ];
}

【问题讨论】:

  • 你如何在控制器中处理它?
  • 它没有到达控制器。 Laravel 的表单请求执行验证,并返回那里。
  • 然后尝试仅使用验证器验证控制器中的数据,如果验证器失败,您可以发送 404 状态码。

标签: laravel http-status-code-404 rules


【解决方案1】:

你可以修改app/Exceptions/Handler.php,我是这样用的

use Illuminate\Database\Eloquent\ModelNotFoundException;

public function render($request, Exception $e)
{
    $status = method_exists($e, 'getStatusCode') ? $e->getStatusCode() : 500;
    //here im using translation, you can set your own message
    $response = [
        'errors' => trans("response.$status.response"),
        'message' => trans("response.$status.message")
    ];

    if (config('app.debug')) {
        $response['exception'] = get_class($e);
        $response['message'] = $e->getMessage();
        $response['trace'] = $e->getTrace();
    }
    //ModelNotFoundException statusCode is 0 so i need to pass it manually 
    if($e instanceof ModelNotFoundException){
        $response['errors'] = new \Illuminate\Support\ViewErrorBag;
        $response['response'] = 404; // im using translation here
        return response()->view("errors.index", $response, 404);
    }
    
    return parent::render($request, $e);
}

在我的刀片中,一个简单的翻译消息:

<p>{{trans("response.{$response}.response")}}</p>
<p>{{trans("response.{$response}.message")}}</p>

【讨论】:

    【解决方案2】:

    我找到了解决方案,但我不是 100% 满意。

    基本上我创建了一个类 (ApiRequest.php) 来扩展 Illuminate 的 FormRequest 类,在这个 ApiRequest 类中我拦截了IlluminateValidationException 并对失败的验证做一些逻辑,检查我的请求是否失败exists() 规则。如果是,我将状态码更改为 404:

    这是我的课:

    abstract class ApiRequest extends IlluminateFormRequest
    {
        /**
         * Handle a failed validation attempt.
         *
         * @param \Illuminate\Contracts\Validation\Validator $validator
         * @return void
         *
         * @throws \GetCandy\Api\Exceptions\ValidationException
         */
        protected function failedValidation(Validator $validator)
        {
            $failedRules = $validator->failed();
            $statusCode = $this->getStatusCode($failedRules);
    
            $response = new JsonResponse([
                'message' => 'The given data is invalid',
                'errors' => $validator->errors(),
            ], $statusCode);
    
            throw new IlluminateValidationException($validator, $response);
        }
    
        private function getStatusCode($failedRules)
        {
            $statusCode = 400;
    
            foreach ($failedRules as $rule) {
                if (Arr::has($rule, "App\Http\Requests\Rules\ValidatePersonExists")) {
                    $statusCode = 404;
                }
            }
    
            return $statusCode;
        }
    }
    

    希望这对某人有所帮助,如果有人有更好的解决方案,请随时发布答案。

    【讨论】:

    • 我使用 Illuminate\Http\Exceptions\HttpResponseException 进行 api 错误验证,并使用 Illuminate\Validation\ValidationException 来处理 failedValidation 中的 formData
    猜你喜欢
    • 2017-12-06
    • 2015-05-01
    • 2015-05-28
    • 2018-05-18
    • 2015-06-29
    • 2018-06-03
    • 2021-09-11
    • 2017-12-01
    • 2020-02-17
    相关资源
    最近更新 更多