本文目录导读:

在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; // 条件不满足时不验证
}
}
总结与建议
- 简单项目:使用基础函数封装即可
- 中型项目:推荐面向对象封装
- 大型项目:强烈建议使用 Symfony Validator 或 Respect Validation 等成熟库
- 性能考虑:注意使用缓存,避免重复创建验证规则实例
- 国际化:规则消息支持多语言配置
选择哪种方案取决于项目规模和复杂度,但始终建议遵循 DRY(Don't Repeat Yourself) 原则,将验证逻辑集中管理。