如何使用自定义规则在Laravel表单请求中抛出404

问题描述

通常,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";
    }
}

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

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

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

解决方法

您可以修改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>
,

我找到了一个解决方案,但我不是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;
    }
}

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...