如果另一个字段已完全通过验证,且不仅仅是被填写,则对该字段进行有条件的验证

前端开发 2026-07-07

realestate\app\Http\Controllers\AuthController.php 拥有注册验证规则和注册方法:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\{Auth, Log};
use Illuminate\Validation\Rules\Password;
use Illuminate\Validation\Validator;

class AuthController extends Controller
{
    private array $register_rules;

    public function __construct(private UserService $service) {
        $this->register_rules = [
            "email" => "required|string|email",
            "password" => ["required", "string", "different:email", Password::min(8)->mixedCase()->numbers()->symbols()],
            "password2" => "same:password",
            "phone" => "required|string|regex:/^\+381 \d{2} \d{6,7}$/mu",
            "first_name" => "required|string|alpha",
            "last_name" => "required|string|alpha",
            "birth_date" => "required|date|before:-18 years"
        ];
    }

    public function register(Request $request)
    {
        // 2 Input validation & sanitization
        // $validated = $request->validate($this->register_rules);

        $validator = Validator::make($request->all(), $this->register_rules);
        $validated = $validator->validate();

        // ...

        // 5 Security logging
        Log::info(LogMessages::auth_controller["register_success"], ["user_id" => $user->id]);
        return redirect()->route("listing_index");
    } // [1]
}

password 不能为空,必须是字符串,并且由字母、数字和特殊字符混合组成。

仅当 password非空且完全有效 时,才对 password2password 进行一致性验证。

realestate\resources\views\auth\register.blade.php

<div class="col-12">
  <div class="input-group">
    <div class="form-floating">
      <input class="form-control" type="password" id="password" name="password">
      <label for="password">Lozinka</label>
    </div>

    <div class="form-floating">
      <input class="form-control" type="password" id="password2" name="password2">
      <label for="password2">Potvrda lozinke</label>
    </div>
  </div>
  @if ($errors->hasAny('password', 'password2'))
    <div class="form-text text-danger">{{ __($errors->first('password')) }}</div>
    <div class="form-text text-danger fw-bold">{{ __($errors->first('password2')) }}</div>
  @endif
</div>

password 的错误显示在带有 _($errors->first('password') 的div中,而 password2 的错误显示在带有 _($errors->first('password2') 的div,并使用粗体文本。

尝试通过在 register 中添加 $validator->after 来解决,但 $validator 实例没有 errors() 方法。

$validator->after(function (Validator $validator) use ($request) {
    $password = $request->get("password");
    $password2 = $request->get("password2");

    if (!$validator->errors()->has("password") && $password !== $password2) $validator->errors()->add("password2", _("password2.confirmed"));
});

解决方案

你这是在重复造轮子。此外,技术上并没有必要只在原密码有效时才验证确认。

来自文档(1, 2):

$validator = Validator::make($request->all(), [
    'password' => ['required', 'confirmed', Password::min(8)],
]);
// Require at least 8 characters...
Password::min(8)

// Require at least one letter...
Password::min(8)->letters()

// Require at least one uppercase and one lowercase letter...
Password::min(8)->mixedCase()

// Require at least one number...
Password::min(8)->numbers()

// Require at least one symbol...
Password::min(8)->symbols()

confirmed

被验证的字段必须有一个与之匹配的字段,字段名为 {field}_confirmation。例如,如果被验证的字段是 password,输入中必须存在一个匹配的 password_confirmation 字段。

你也可以传一个自定义的确认字段名。例如,confirmed:repeat_username 将期望字段 repeat_username 与被验证的字段相匹配。

如果要使用这个,请记得把 password2 重命名为 password_confirmation(因为这是一个确认字段,而不是第二个密码,措辞更贴切)。

据我所知,没有像“只有当这个字段已被验证为有效时才验证”的规则,所以你要么坚持使用验证器的 after() 方法,要么添加一个自定义规则。

如果你的 $validator 没有 errors() 方法,你是在搞错。它应该在你通过 make() 初始化后就可用。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章