PHP项目表单验证规则如何复用封装

wen PHP项目 24

本文目录导读:

PHP项目表单验证规则如何复用封装

  1. 基础函数封装
  2. 面向对象封装
  3. 使用现有库(推荐)
  4. 高级封装:规则组合与自定义
  5. 总结与建议

在PHP项目中,实现表单验证规则的复用封装,通常有几种主流且成熟的模式,我会从最基础的函数封装,到较为高级的类封装,推荐几种实用方案。

基础函数封装

简单的验证函数集

<?php
// validators.php
function validateRequired($value, $fieldName = '') {
    if (empty(trim($value))) {
        return "$fieldName 不能为空";
    }
    return true;
}
function validateEmail($value, $fieldName = '') {
    if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
        return "$fieldName 格式不正确";
    }
    return true;
}
function validateMinLength($value, $min, $fieldName = '') {
    if (mb_strlen($value) < $min) {
        return "$fieldName 至少需要 $min 个字符";
    }
    return true;
}
function validateMaxLength($value, $max, $fieldName = '') {
    if (mb_strlen($value) > $max) {
        return "$fieldName 不能超过 $max 个字符";
    }
    return true;
}
function validateNumeric($value, $fieldName = '') {
    if (!is_numeric($value)) {
        return "$fieldName 必须是数字";
    }
    return true;
}

验证规则执行器

<?php
// validator.php
function validate($data, $rules) {
    $errors = [];
    foreach ($rules as $field => $ruleSet) {
        $value = $data[$field] ?? '';
        $fieldName = $ruleSet['label'] ?? $field;
        foreach ($ruleSet as $rule => $param) {
            if ($rule === 'label') continue;
            $result = applyRule($rule, $value, $param, $fieldName);
            if ($result !== true) {
                $errors[$field][] = $result;
                break; // 一条规则失败就不再检查其他规则
            }
        }
    }
    return $errors;
}
function applyRule($rule, $value, $param, $fieldName) {
    switch ($rule) {
        case 'required':
            return validateRequired($value, $fieldName);
        case 'email':
            return validateEmail($value, $fieldName);
        case 'min':
            return validateMinLength($value, $param, $fieldName);
        case 'max':
            return validateMaxLength($value, $param, $fieldName);
        case 'numeric':
            return validateNumeric($value, $fieldName);
        default:
            return true;
    }
}

使用示例

<?php
// 调用
$data = [
    'username' => 'john',
    'email' => 'invalid-email',
    'age' => 'abc'
];
$rules = [
    'username' => [
        'label' => '用户名',
        'required' => true,
        'min' => 3,
        'max' => 20
    ],
    'email' => [
        'label' => '邮箱',
        'required' => true,
        'email' => true
    ],
    'age' => [
        'label' => '年龄',
        'required' => true,
        'numeric' => true
    ]
];
$errors = validate($data, $rules);
print_r($errors);

面向对象封装

验证规则类

<?php
// Rule.php
abstract class Rule {
    protected $message;
    public function __construct($message = null) {
        $this->message = $message;
    }
    abstract public function validate($value): bool;
    public function message($fieldName): string {
        return $this->message ?? "{$fieldName} 验证失败";
    }
}
class Required extends Rule {
    public function validate($value): bool {
        return !empty(trim($value));
    }
    public function message($fieldName): string {
        return $this->message ?? "{$fieldName} 不能为空";
    }
}
class Email extends Rule {
    public function validate($value): bool {
        return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
    }
    public function message($fieldName): string {
        return $this->message ?? "{$fieldName} 格式不正确";
    }
}
class MinLength extends Rule {
    private $min;
    public function __construct($min, $message = null) {
        $this->min = $min;
        parent::__construct($message);
    }
    public function validate($value): bool {
        return mb_strlen($value) >= $this->min;
    }
    public function message($fieldName): string {
        return $this->message ?? "{$fieldName} 至少需要 {$this->min} 个字符";
    }
}

验证器类

<?php
// Validator.php
class Validator {
    private $data;
    private $rules = [];
    private $errors = [];
    public function __construct(array $data) {
        $this->data = $data;
    }
    public function addRule(string $field, Rule $rule, string $fieldName = null) {
        $this->rules[] = [
            'field' => $field,
            'rule' => $rule,
            'fieldName' => $fieldName ?? $field
        ];
        return $this; // 链式调用支持
    }
    public function validate(): bool {
        $this->errors = [];
        foreach ($this->rules as $ruleSet) {
            $value = $this->data[$ruleSet['field']] ?? '';
            if (!$ruleSet['rule']->validate($value)) {
                $this->errors[$ruleSet['field']][] = 
                    $ruleSet['rule']->message($ruleSet['fieldName']);
            }
        }
        return empty($this->errors);
    }
    public function getErrors(): array {
        return $this->errors;
    }
}

使用示例

<?php
// 使用
$data = [
    'username' => '',
    'email' => 'invalid',
    'password' => '123'
];
$validator = new Validator($data);
$validator
    ->addRule('username', new Required(), '用户名')
    ->addRule('username', new MinLength(3), '用户名')
    ->addRule('email', new Required(), '邮箱')
    ->addRule('email', new Email(), '邮箱')
    ->addRule('password', new MinLength(6), '密码');
if ($validator->validate()) {
    echo "验证通过";
} else {
    print_r($validator->getErrors());
}

使用现有库(推荐)

对于生产环境,推荐使用成熟的开源验证库:

respect/validation

<?php
use Respect\Validation\Validator as v;
$validator = v::attribute('username', v::alnum()->length(3, 20))
    ->attribute('email', v::email())
    ->attribute('age', v::intVal()->between(18, 100));
try {
    $validator->assert($data);
    echo "验证通过";
} catch (\Respect\Validation\Exceptions\NestedValidationException $e) {
    print_r($e->getMessages());
}

symfony/validator

<?php
use Symfony\Component\Validator\Validation;
use Symfony\Component\Validator\Constraints as Assert;
$validator = Validation::createValidator();
$constraints = new Assert\Collection([
    'username' => [
        new Assert\NotBlank(['message' => '用户名不能为空']),
        new Assert\Length(['min' => 3, 'max' => 20])
    ],
    'email' => new Assert\Email(),
    'age' => new Assert\Range(['min' => 18, 'max' => 100])
]);
$violations = $validator->validate($data, $constraints);
if (count($violations) > 0) {
    foreach ($violations as $violation) {
        echo $violation->getMessage();
    }
}

高级封装:规则组合与自定义

支持规则组合

<?php
// 组合验证
$validator->addRule('password', new Required())
    ->addRule('password', new MinLength(8))
    ->addRule('password', new Regex('/[A-Z]/', '密码必须包含大写字母'))
    ->addRule('password', new Regex('/[0-9]/', '密码必须包含数字'));
// 或者使用 OR 组合
$validator->addRule('phone', new AnyOf([
    new Phone(),
    new Email()
], '请输入有效的手机号或邮箱'));

条件验证

<?php
class RequiredIf extends Rule {
    private $condition;
    public function __construct(callable $condition, $message = null) {
        $this->condition = $condition;
        parent::__construct($message);
    }
    public function validate($value): bool {
        if (($this->condition)()) {
            return !empty(trim($value));
        }
        return true; // 条件不满足时不验证
    }
}

总结与建议

  1. 简单项目:使用基础函数封装即可
  2. 中型项目:推荐面向对象封装
  3. 大型项目:强烈建议使用 Symfony Validator 或 Respect Validation 等成熟库
  4. 性能考虑:注意使用缓存,避免重复创建验证规则实例
  5. 国际化:规则消息支持多语言配置

选择哪种方案取决于项目规模和复杂度,但始终建议遵循 DRY(Don't Repeat Yourself) 原则,将验证逻辑集中管理。

抱歉,评论功能暂时关闭!