Laravel 自定义验证规则的验证规则组合与验证逻辑的条件分支

🎤 Laravel 自定义验证规则的“组合拳”与“条件分支”讲座

各位老铁们,大家好!今天咱们来聊聊 Laravel 中自定义验证规则的那些事儿。别看这玩意儿名字高大上,其实它就像你家楼下卖煎饼果子的大爷一样平易近人。只要你掌握了它的套路,分分钟让你的表单验证变得优雅又高效。

准备好了吗?那咱们就开讲啦!😎


📋 讲座大纲

  1. 什么是自定义验证规则?
  2. 如何创建和使用自定义验证规则?
  3. 验证规则的“组合拳”:多个规则一起用
  4. 验证逻辑的“条件分支”:根据场景动态调整
  5. 实战演练:一个复杂的表单验证案例
  6. 总结 & Q&A

1. 什么是自定义验证规则?

在 Laravel 中,默认提供了很多现成的验证规则(比如 requiredemailmin 等),但有时候这些规则并不能完全满足我们的需求。这时候,就需要我们自己动手,丰衣足食——也就是创建自定义验证规则。

简单来说,自定义验证规则就是一种扩展机制,让我们可以定义自己的验证逻辑。举个栗子,假如你想验证用户输入的密码是否包含至少一个特殊字符,Laravel 默认是没有这个规则的,但我们可以轻松实现它。


2. 如何创建和使用自定义验证规则?

方法一:使用匿名函数(Closure)

这是最简单的自定义验证方式。直接在验证规则中传入一个 Closure 函数即可。

$validator = Validator::make($request->all(), [
    'password' => [
        'required',
        function ($attribute, $value, $fail) {
            if (!preg_match('/[!@#$%^&*]/', $value)) {
                $fail($attribute . ' 必须包含至少一个特殊字符。');
            }
        },
    ],
]);

💡 小贴士:这种方式适合简单的场景,但如果规则复杂或者需要复用,建议用下面的方法。


方法二:使用 Rule 对象

Laravel 提供了一个 Rule 类,可以用来封装更复杂的验证逻辑。

use IlluminateValidationRule;

$validator = Validator::make($request->all(), [
    'password' => [
        'required',
        new Rule(function ($attribute, $value, $fail) {
            if (!preg_match('/[!@#$%^&*]/', $value)) {
                $fail('密码必须包含至少一个特殊字符。');
            }
        }),
    ],
]);

方法三:自定义验证规则类

如果你觉得上面两种方法还不够优雅,那就试试创建一个独立的验证规则类吧!

步骤 1:生成规则类

php artisan make:rule PasswordContainsSpecialCharacter

步骤 2:实现验证逻辑

打开生成的类文件(app/Rules/PasswordContainsSpecialCharacter.php),实现 passesmessage 方法。

namespace AppRules;

use IlluminateContractsValidationRule;

class PasswordContainsSpecialCharacter implements Rule
{
    public function passes($attribute, $value)
    {
        return preg_match('/[!@#$%^&*]/', $value);
    }

    public function message()
    {
        return '密码必须包含至少一个特殊字符。';
    }
}

步骤 3:使用规则类

$validator = Validator::make($request->all(), [
    'password' => ['required', new PasswordContainsSpecialCharacter()],
]);

3. 验证规则的“组合拳”:多个规则一起用

很多时候,我们需要对同一个字段应用多个验证规则。比如,用户名必须是唯一的,同时长度不能超过 20 个字符。

$validator = Validator::make($request->all(), [
    'username' => [
        'required',
        'string',
        'max:20',
        Rule::unique('users'),
    ],
]);

💡 小贴士:规则的顺序很重要!如果某个规则失败了,后面的规则就不会再执行了。所以,把耗时的规则(比如数据库查询)放在最后。


4. 验证逻辑的“条件分支”:根据场景动态调整

有时候,验证规则需要根据不同的场景动态变化。比如,注册时需要验证邮箱是否唯一,而登录时只需要验证邮箱是否存在。

使用 sometimes 方法

$validator = Validator::make($request->all(), [
    'email' => 'required|email',
]);

if ($action === 'register') {
    $validator->sometimes('email', 'unique:users', function ($input) {
        return !empty($input->email);
    });
} elseif ($action === 'login') {
    $validator->sometimes('email', 'exists:users', function ($input) {
        return !empty($input->email);
    });
}

使用 when 方法

Laravel 9+ 提供了更简洁的 when 方法:

$validator = Validator::make($request->all(), [
    'email' => 'required|email',
]);

$validator->sometimes('email', 'unique:users', function () use ($action) {
    return $action === 'register';
});

$validator->sometimes('email', 'exists:users', function () use ($action) {
    return $action === 'login';
});

5. 实战演练:一个复杂的表单验证案例

假设我们要实现一个用户注册表单,要求如下:

  • 用户名必须是唯一的,且长度不超过 20 个字符。
  • 密码必须包含至少一个大写字母、一个小写字母和一个数字。
  • 如果用户选择了“记住我”选项,则需要额外验证验证码。
use AppRulesPasswordComplexity;
use IlluminateSupportFacadesValidator;

$validator = Validator::make($request->all(), [
    'username' => ['required', 'string', 'max:20', Rule::unique('users')],
    'password' => ['required', new PasswordComplexity()],
]);

if ($request->has('remember_me')) {
    $validator->sometimes('captcha', 'required|captcha', function ($input) {
        return true;
    });
}

if ($validator->fails()) {
    return redirect()->back()->withErrors($validator)->withInput();
}

其中,PasswordComplexity 是一个自定义规则类:

namespace AppRules;

use IlluminateContractsValidationRule;

class PasswordComplexity implements Rule
{
    public function passes($attribute, $value)
    {
        return preg_match('/[A-Z]/', $value) && // 至少一个大写字母
               preg_match('/[a-z]/', $value) && // 至少一个小写字母
               preg_match('/[0-9]/', $value);   // 至少一个数字
    }

    public function message()
    {
        return '密码必须包含至少一个大写字母、一个小写字母和一个数字。';
    }
}

6. 总结 & Q&A

今天的讲座就到这里啦!我们学习了以下内容:

  • 如何创建和使用自定义验证规则(Closure、Rule 对象、规则类)。
  • 如何将多个规则组合在一起。
  • 如何根据场景动态调整验证逻辑。

如果有任何疑问,欢迎在评论区提问!我会像 Stack Overflow 的大神一样,为你解答困惑 😄

最后,送给大家一句话:"Validation is not just about rules; it’s about making your application more robust and user-friendly." —— Laravel 官方文档 ❤️

下次见咯!👋

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注