通常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 IlluminateDatabaseEloquentModelNotFoundException;
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 IlluminateSupportViewErrorBag;
$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 IlluminateContractsValidationValidator $validator
* @return void
*
* @throws GetCandyApiExceptionsValidationException
*/
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, "AppHttpRequestsRulesValidatePersonExists")) {
$statusCode = 404;
}
}
return $statusCode;
}
}
希望这能帮助到某人,如果有人有更好的解决方案,请随时发布答案。