问题描述
通常,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;
}
}
希望这对某人有帮助,如果有人有更好的解决方案,请随时发布答案。