本文目录导读:

我来为您设计一个PHP验证器工厂模式的完整实现,包含示例和说明。
验证器接口
<?php
// ValidatorInterface.php
namespace App\Validators;
interface ValidatorInterface
{
/**
* 执行验证逻辑
* @param mixed $value 待验证的值
* @param array $options 验证选项
* @return bool 验证是否通过
*/
public function validate($value, array $options = []): bool;
/**
* 获取验证失败的错误消息
* @return string
*/
public function getMessage(): string;
/**
* 设置错误消息
* @param string $message
* @return self
*/
public function setMessage(string $message): self;
}
具体验证器实现
<?php
// RequiredValidator.php
namespace App\Validators;
class RequiredValidator implements ValidatorInterface
{
private $message = '该字段是必填的';
public function validate($value, array $options = []): bool
{
if (isset($options['message'])) {
$this->setMessage($options['message']);
}
if ($value === null || $value === '') {
return false;
}
if (is_array($value) && empty($value)) {
return false;
}
return true;
}
public function getMessage(): string
{
return $this->message;
}
public function setMessage(string $message): self
{
$this->message = $message;
return $this;
}
}
<?php
// EmailValidator.php
namespace App\Validators;
class EmailValidator implements ValidatorInterface
{
private $message = '邮箱格式不正确';
public function validate($value, array $options = []): bool
{
if (isset($options['message'])) {
$this->setMessage($options['message']);
}
if (empty($value)) {
return true; // 可选字段,如果必填则使用 RequiredValidator
}
return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
}
public function getMessage(): string
{
return $this->message;
}
public function setMessage(string $message): self
{
$this->message = $message;
return $this;
}
}
<?php
// LengthValidator.php
namespace App\Validators;
class LengthValidator implements ValidatorInterface
{
private $message = '长度不符合要求';
public function validate($value, array $options = []): bool
{
$min = $options['min'] ?? 0;
$max = $options['max'] ?? PHP_INT_MAX;
if (isset($options['message'])) {
$this->setMessage($options['message']);
}
$length = mb_strlen($value, 'UTF-8');
if ($length < $min) {
$this->setMessage("长度不能小于 {$min} 个字符");
return false;
}
if ($length > $max) {
$this->setMessage("长度不能大于 {$max} 个字符");
return false;
}
return true;
}
public function getMessage(): string
{
return $this->message;
}
public function setMessage(string $message): self
{
$this->message = $message;
return $this;
}
}
<?php
// NumericValidator.php
namespace App\Validators;
class NumericValidator implements ValidatorInterface
{
private $message = '必须是数字';
public function validate($value, array $options = []): bool
{
if (isset($options['message'])) {
$this->setMessage($options['message']);
}
if (!is_numeric($value)) {
return false;
}
// 检查范围
if (isset($options['min']) && $value < $options['min']) {
$this->setMessage("数字不能小于 {$options['min']}");
return false;
}
if (isset($options['max']) && $value > $options['max']) {
$this->setMessage("数字不能大于 {$options['max']}");
return false;
}
return true;
}
public function getMessage(): string
{
return $this->message;
}
public function setMessage(string $message): self
{
$this->message = $message;
return $this;
}
}
<?php
// RegexValidator.php
namespace App\Validators;
class RegexValidator implements ValidatorInterface
{
private $message = '格式不正确';
public function validate($value, array $options = []): bool
{
if (!isset($options['pattern'])) {
throw new \InvalidArgumentException('正则表达式验证器需要提供pattern选项');
}
if (isset($options['message'])) {
$this->setMessage($options['message']);
}
return preg_match($options['pattern'], $value) === 1;
}
public function getMessage(): string
{
return $this->message;
}
public function setMessage(string $message): self
{
$this->message = $message;
return $this;
}
}
验证器工厂
<?php
// ValidatorFactory.php
namespace App\Validators;
use InvalidArgumentException;
class ValidatorFactory
{
/**
* @var array 验证器别名映射
*/
private static $aliases = [
'required' => RequiredValidator::class,
'email' => EmailValidator::class,
'length' => LengthValidator::class,
'numeric' => NumericValidator::class,
'integer' => NumericValidator::class,
'regex' => RegexValidator::class,
];
/**
* @var array 已创建的验证器实例缓存
*/
private static $instances = [];
/**
* 创建验证器实例
* @param string $type 验证器类型
* @param array $options 验证器选项
* @return ValidatorInterface
* @throws InvalidArgumentException
*/
public static function create(string $type, array $options = []): ValidatorInterface
{
$class = self::resolveClass($type);
// 使用选项作为缓存键的一部分
$cacheKey = $type . ':' . md5(json_encode($options));
if (!isset(self::$instances[$cacheKey])) {
self::$instances[$cacheKey] = new $class();
}
return self::$instances[$cacheKey];
}
/**
* 解析验证器类名
* @param string $type
* @return string
* @throws InvalidArgumentException
*/
private static function resolveClass(string $type): string
{
$type = strtolower($type);
if (isset(self::$aliases[$type])) {
return self::$aliases[$type];
}
// 尝试按类名解析(支持App\Validators\CustomValidator格式)
$class = 'App\\Validators\\' . ucfirst($type) . 'Validator';
if (class_exists($class)) {
return $class;
}
throw new InvalidArgumentException("未知的验证器类型: {$type}");
}
/**
* 注册自定义验证器
* @param string $alias 别名
* @param string $class 类名
* @throws InvalidArgumentException
*/
public static function register(string $alias, string $class): void
{
if (!class_exists($class) || !in_array(ValidatorInterface::class, class_implements($class))) {
throw new InvalidArgumentException("{$class} 必须实现 ValidatorInterface");
}
self::$aliases[strtolower($alias)] = $class;
}
/**
* 清理实例缓存
*/
public static function clearCache(): void
{
self::$instances = [];
}
}
验证器管理器(集成多个验证器)
<?php
// ValidationManager.php
namespace App\Validators;
class ValidationManager
{
private $rules = [];
private $data = [];
private $errors = [];
public function __construct(array $data = [])
{
$this->data = $data;
}
/**
* 添加验证规则
* @param string $field 字段名
* @param string $validator 验证器类型
* @param array $options 验证选项
* @return self
*/
public function addRule(string $field, string $validator, array $options = []): self
{
$this->rules[$field][] = [
'validator' => $validator,
'options' => $options
];
return $this;
}
/**
* 批量添加验证规则
* @param array $rules 格式: ['字段名' => [['validator' => 'required'], ...]]
* @return self
*/
public function addRules(array $rules): self
{
foreach ($rules as $field => $fieldRules) {
foreach ($fieldRules as $rule) {
$validator = $rule['validator'] ?? null;
if (!$validator) {
continue;
}
$options = $rule['options'] ?? [];
$this->addRule($field, $validator, $options);
}
}
return $this;
}
/**
* 执行验证
* @return bool
*/
public function validate(): bool
{
$this->errors = [];
foreach ($this->rules as $field => $rules) {
$value = $this->data[$field] ?? null;
foreach ($rules as $rule) {
$validator = ValidatorFactory::create(
$rule['validator'],
$rule['options']
);
if (!$validator->validate($value, $rule['options'])) {
$this->errors[$field][] = $validator->getMessage();
break; // 一个字段只显示第一个错误
}
}
}
return empty($this->errors);
}
/**
* 获取所有错误信息
* @return array
*/
public function getErrors(): array
{
return $this->errors;
}
/**
* 获取指定字段的错误信息
* @param string $field
* @return array
*/
public function getFieldErrors(string $field): array
{
return $this->errors[$field] ?? [];
}
}
使用示例
<?php
// usage.php
require 'vendor/autoload.php';
use App\Validators\ValidatorFactory;
use App\Validators\ValidationManager;
use App\Validators\CustomValidators\PhoneValidator;
// 1. 基本用法
$emailValidator = ValidatorFactory::create('email');
$isValid = $emailValidator->validate('user@example.com');
echo $isValid ? "Email有效\n" : "Email无效\n";
// 2. 带选项的验证
$lengthValidator = ValidatorFactory::create('length', ['min' => 3, 'max' => 10]);
$isValid = $lengthValidator->validate('Hello');
echo $isValid ? "长度有效\n" : "长度无效\n";
// 3. 注册自定义验证器
ValidatorFactory::register('phone', PhoneValidator::class);
// 4. 使用验证管理器
$data = [
'username' => 'JohnDoe',
'email' => 'john@example.com',
'age' => '25',
'phone' => '13800138000'
];
$validationManager = new ValidationManager($data);
$validationManager
->addRule('username', 'required', ['message' => '用户名不能为空'])
->addRule('username', 'length', ['min' => 3, 'max' => 20, 'message' => '用户名长度需在3-20之间'])
->addRule('email', 'required', ['message' => '邮箱不能为空'])
->addRule('email', 'email', ['message' => '邮箱格式不正确'])
->addRule('age', 'numeric', ['min' => 18, 'max' => 100])
->addRule('phone', 'phone', ['message' => '手机号格式不正确']);
if ($validationManager->validate()) {
echo "所有验证通过!\n";
} else {
print_r($validationManager->getErrors());
}
// 5. 批量添加规则示例
$rules = [
'name' => [
['validator' => 'required', 'options' => ['message' => '姓名必填']],
['validator' => 'length', 'options' => ['min' => 2, 'max' => 50, 'message' => '姓名长度需在2-50之间']]
],
'age' => [
['validator' => 'numeric', 'options' => ['min' => 1, 'max' => 150, 'message' => '年龄需在1-150之间']]
]
];
$manager = new ValidationManager([
'name' => 'John',
'age' => 30
]);
$manager->addRules($rules);
if ($manager->validate()) {
echo "批量规则验证通过!\n";
} else {
print_r($manager->getErrors());
}
// 6. 自定义验证器类
// CustomValidators/PhoneValidator.php
namespace App\Validators\CustomValidators;
use App\Validators\ValidatorInterface;
class PhoneValidator implements ValidatorInterface
{
private $message = '手机号格式不正确';
public function validate($value, array $options = []): bool
{
if (isset($options['message'])) {
$this->setMessage($options['message']);
}
if (empty($value)) {
return true;
}
// 中国大陆手机号简单验证
return preg_match('/^1[3-9]\d{9}$/', $value) === 1;
}
public function getMessage(): string
{
return $this->message;
}
public function setMessage(string $message): self
{
$this->message = $message;
return $this;
}
}
高级特性
<?php
// AdvancedValidatorFactory.php - 支持闭包验证器
namespace App\Validators;
class AdvancedValidatorFactory
{
private static $closures = [];
/**
* 注册闭包验证器
* @param string $name
* @param callable $callback 接收值和选项,返回bool
*/
public static function registerClosure(string $name, callable $callback): void
{
self::$closures[$name] = $callback;
}
/**
* 创建闭包验证器
*/
public static function createClosure(string $name, callable $callback): ValidatorInterface
{
return new class($name, $callback) implements ValidatorInterface {
private $name;
private $callback;
private $message;
public function __construct(string $name, callable $callback)
{
$this->name = $name;
$this->callback = $callback;
}
public function validate($value, array $options = []): bool
{
$this->message = $options['message'] ?? "验证失败";
return call_user_func($this->callback, $value, $options);
}
public function getMessage(): string
{
return $this->message;
}
public function setMessage(string $message): self
{
$this->message = $message;
return $this;
}
};
}
}
// 使用闭包验证器
AdvancedValidatorFactory::registerClosure('even', function($value) {
return $value % 2 === 0;
});
$validator = AdvancedValidatorFactory::createClosure('even',
AdvancedValidatorFactory::$closures['even']
);
测试类
<?php
// tests/ValidatorTest.php
use PHPUnit\Framework\TestCase;
use App\Validators\ValidatorFactory;
use App\Validators\ValidationManager;
class ValidatorTest extends TestCase
{
public function testEmailValidation()
{
$validator = ValidatorFactory::create('email');
$this->assertTrue($validator->validate('test@example.com'));
$this->assertFalse($validator->validate('invalid-email'));
}
public function testRequiredValidation()
{
$validator = ValidatorFactory::create('required');
$this->assertFalse($validator->validate(''));
$this->assertFalse($validator->validate(null));
$this->assertTrue($validator->validate('some value'));
}
public function testValidationManager()
{
$data = [
'name' => 'John',
'email' => 'john@example.com'
];
$manager = new ValidationManager($data);
$manager
->addRule('name', 'required')
->addRule('name', 'length', ['min' => 2])
->addRule('email', 'email');
$this->assertTrue($manager->validate());
$this->assertEmpty($manager->getErrors());
}
}
Composer 配置
{
"name": "validator-factory",
"description": "PHP Validator Factory Pattern",
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"require": {
"php": ">=7.4"
}
}
核心优势
- 灵活扩展:新增验证器只需实现接口并注册
- 代码复用:验证器可重用,避免重复代码
- 配置集中:验证规则配置清晰,易于维护
- 错误处理:统一的错误消息管理
- 性能优化:实例缓存机制
- 开闭原则:对扩展开放,对修改关闭
这个验证器工厂模式适合各种PHP项目,从简单表单验证到复杂的数据校验场景都能很好的支持。