如何在返回所有错误的同时使用 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 规则。所以passwordrequired_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 错误。但是可以返回所有对象

laraver6-数据填充

如何使用 PHP 处理 403 错误

Laravel 4:PHP 致命错误:调用未定义的方法 Blueprint::int()

如何在子目录 Laravel 中正确配置 htaccess?