如何在返回所有错误的同时使用 PHP laravel 中的公共类有选择地验证多个字段
Posted
技术标签:
【中文标题】如何在返回所有错误的同时使用 PHP laravel 中的公共类有选择地验证多个字段【英文标题】:How to validate multiple fields selectively using a common class in PHP laravel while returning all errors 【发布时间】:2022-01-14 13:29:50 【问题描述】:刚开始我的第一个 php laravel 项目,我有这个
UserRepository.php
public function validateNewEmail(Request $request, $emailName)
$request->validate([
$emailName => ['required', 'email', 'unique:users'],
]);
public function validateNewPassword(Request $request, $passwordName)
$request->validate(
// rule
[
$passwordName => ['required', 'min:8',
'regex: // some long long regex'
],
// message
[
$passwordName.".regex" => "Your new password must be more than 8 characters long, should contain at-least 1 uppercase, 1 lowercase, 1 numeric and 1 special character.",
]
);
// Usr Id is by itself as it might be optional in registering.
public function validateNewUsrId(Request $request, $userIdName)
$request->validate([
$userIdName => 'required|unique:users',
]);
然后我可以像这样在我的控制器中轻松使用这个存储库。
$this->userRepository->validateNewEmail($request, "email");
$this->userRepository->validateNewPassword($request, "password");
$this->userRepository->validateNewUsrId($request, "usr_id");
原因是因为可能有多个控制器使用相同的规则,所以把它们放在一个地方比较好
但是,我意识到这个方法不起作用,因为它只返回第一个错误。比如邮箱和密码都错了,只有邮箱错误会返回给前端。
实现我想要的最佳方式是什么?我想将我所有的验证/规则放在一个地方以供重复使用。
我的第一个解决方案是:每个函数都返回错误 MessageBag,然后将其连接在一起。我将使用return $validator->errors();
来返回可以在这里找到的MessageBag https://laravel.com/docs/8.x/validation#retrieving-the-first-error-message-for-a-field
但是我有点不喜欢它,因为为了检查是否发生错误,我需要检查 MessageBag 是否为空,然后抛出一个看起来有点奇怪的错误。
我想到的另一种方法是返回 规则,这样我就可以将它们加入我的控制器中,然后一次性验证所有内容。这似乎更好,但我还必须结合 错误消息,如果有多个,这可能会有点棘手(因为密钥不固定,请参见代码 $passwordName.".regex"
例如。),因为我需要更新每条消息的密钥。
对我来说最好的方法是,是否可以为每个函数返回一个验证器,然后使用某种 Validate::ValidateAll 函数?这可能吗?
这通常是如何实现的?
【问题讨论】:
php artisan make:rule
laravel.com/docs/8.x/validation#custom-validation-rules
您还应该使用表单请求验证。控制器中的验证是一种非常过时的方法。
另请注意 Laravel 内置了对所有常见密码验证场景的支持。您应该尽可能使用这些,而不是尝试使用正则表达式编写您自己的。 laravel.com/docs/8.x/validation#validating-passwords
@miken32 我明白了,表单请求验证似乎是一个很好的方法。唯一的缺点是每个控制器都必须为特定字段使用相同的名称。例如,我不能命名一个“密码”和另一个“密码”。但我想这没关系。只是检查一下,所以如果我想有单独的密码、电子邮件和姓名请求,我必须提出 3 个不同的请求类,是吗?因为例如注册可能需要电子邮件,但更改密码不需要。
不一定,您可以使用required_without_all
规则。所以password
是required_without_all:email,name
等等laravel.com/docs/8.x/validation#rule-required-without-all
【参考方案1】:
现代 Laravel 应用程序通常使用 form request validation。使用这种方法,Laravel 会自动处理所有验证并返回错误消息。只需编写表单请求类,然后在控制器方法中使用它代替 Request
:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Password;
class MyFormRequest extends FormRequest
/**
* Get the validation rules that apply to the request.
*/
public function rules(): array
return [
'email' => ['required', 'email', 'unique:users'],
'password' => [
'required',
Password::min(8)->mixedCase()->numbers()->symbols()
],
'usrid' => ['required', 'unique:users'],
];
public method store(MyFormRequest $request)
// $request has been validated, no further checking needed
请注意,我使用的是 Laravel 的 built-in password validation rules,而不是依赖于“long long regex”。
【讨论】:
以上是关于如何在返回所有错误的同时使用 PHP laravel 中的公共类有选择地验证多个字段的主要内容,如果未能解决你的问题,请参考以下文章
使用Larave5.6l提交POST请求出现The page has expired due to inactivity错误
当我尝试从 PHP 对象/数组返回值时,出现 500 错误。但是可以返回所有对象