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

如何使用自定义规则抛出404 in-Laravel表单请求,laravel,http-status-code-404,rules,Laravel,Http Status Code 404,Rules,通常,如果验证失败,Laravel的表单请求会返回一个通用的400代码,如下所示: { "message": "The given data is invalid", "errors": { "person_id": [ "A person with ID c6b853ec-b53e-4c35-b633-3b1c2f27869c does not exist"

通常,如果验证失败,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],
    ];
}

您可以修改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>
{{trans(“response.{$response}.response”)}

{{trans(“response.{$response}.message”)}


您可以修改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>
{{trans(“response.{$response}.response”)}

{{trans(“response.{$response}.message”)}


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

基本上,我创建了一个类(ApiRequest.php)来扩展Illumb的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;
    }
}

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

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

基本上,我创建了一个类(ApiRequest.php)来扩展Illumb的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;
    }
}

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

您在控制器中如何处理它?控制器没有收到它。Laravel的表单请求执行验证,然后返回。然后尝试仅使用验证器验证控制器中的数据,如果验证器失败,您可以发送404状态码。您如何在控制器中处理它?它不会到达控制器。Laravel的表单请求执行验证,然后尝试仅使用验证程序验证控制器中的数据,如果验证程序失败,则可以使用Illumb\Http\Exceptions\HttpResponseException发送404 status code.im进行api错误验证,并使用Illumb\validation\ValidationException发送failedValidationim中的formDataIllumb\Http\Exceptions\HttpResponseException用于api错误验证,Illumb\validation\ValidationException用于failedValidation中的formData