如何在返回所有错误时使用 PHP laravel 中的公共 class 选择性地验证多个字段

How to validate multiple fields selectively using a common class in PHP laravel while returning all errors

刚开始我的第一个 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");

原因是可能有多个控制器使用相同的规则,所以放在一个地方比较好

但是,我意识到这个 方法不起作用,因为它 return 只是第一个错误 。例如,当电子邮件和密码都错误时,只有电子邮件错误 returned 到前端。

实现我想要的最好方法是什么?我想把我所有的 validation/rules 放在一个地方以便重复使用。

我的第一个解决方案是:每个函数 returns 错误 MessageBag,然后将其连接在一起。我将使用 return $validator->errors(); 到 return 可以在此处找到的 MessageBag https://laravel.com/docs/8.x/validation#retrieving-the-first-error-message-for-a-field

但是我有点不喜欢它,因为为了检查是否发生错误,我需要检查 MessageBag 是否为空,然后抛出一个看起来有点奇怪的错误。

我想到的另一种方法是 return 规则 ,这样我就可以在我的控制器中加入它们,然后一次性验证所有规则。这看起来更好,但我还必须合并 错误消息 ,如果有多个,这可能有点棘手(因为密钥不固定,请参见代码 $passwordName.".regex"例如),因为我需要更新每条消息的密钥。

对我来说最好的方法是,如果我可以 return 每个函数的验证器,然后使用某种 Validate::ValidateAll 函数?这可能吗?

这通常是如何实现的?

现代 Laravel 应用程序通常使用 form request validation。使用这种方法,Laravel 会自动处理所有验证和 returns 错误消息。只需编写您的表单请求 class,然后在您的控制器方法中使用它代替 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”。