Files
FendxPHP/app/Validate/BaseValidator.php

427 lines
11 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
namespace App\Validate;
use Fendx\Web\Request\Request;
/**
* 验证器基类
*/
abstract class BaseValidator
{
/**
* 验证规则
*/
abstract protected function getRules(): array;
/**
* 验证请求数据
*/
public function validate(Request $request): array
{
return $this->validateData($request->all(), $this->getRules());
}
/**
* 验证数组数据
*/
public function validateData(array $data, array $rules): array
{
$errors = [];
foreach ($rules as $field => $rule) {
$value = $data[$field] ?? null;
$fieldErrors = $this->validateField($field, $value, $rule, $data);
if (!empty($fieldErrors)) {
$errors[$field] = $fieldErrors;
}
}
return $errors;
}
/**
* 验证单个字段
*/
protected function validateField(string $field, mixed $value, array $rule, array $data): array
{
$errors = [];
// 必填验证
if ($rule['required'] && ($value === null || $value === '')) {
$errors[] = $rule['message'] ?? "字段 {$field} 必填";
return $errors;
}
// 如果字段不是必填且为空,跳过其他验证
if (!$rule['required'] && ($value === null || $value === '')) {
return $errors;
}
// 类型验证
if (isset($rule['type'])) {
$typeError = $this->validateType($field, $value, $rule['type']);
if ($typeError) {
$errors[] = $typeError;
}
}
// 长度验证
if (isset($rule['min'])) {
$minError = $this->validateMin($field, $value, $rule['min']);
if ($minError) {
$errors[] = $minError;
}
}
if (isset($rule['max'])) {
$maxError = $this->validateMax($field, $value, $rule['max']);
if ($maxError) {
$errors[] = $maxError;
}
}
// 数值范围验证
if (isset($rule['min_value'])) {
$minValueError = $this->validateMinValue($field, $value, $rule['min_value']);
if ($minValueError) {
$errors[] = $minValueError;
}
}
if (isset($rule['max_value'])) {
$maxValueError = $this->validateMaxValue($field, $value, $rule['max_value']);
if ($maxValueError) {
$errors[] = $maxValueError;
}
}
// 正则表达式验证
if (isset($rule['pattern'])) {
$patternError = $this->validatePattern($field, $value, $rule['pattern']);
if ($patternError) {
$errors[] = $patternError;
}
}
// 枚举值验证
if (isset($rule['enum'])) {
$enumError = $this->validateEnum($field, $value, $rule['enum']);
if ($enumError) {
$errors[] = $enumError;
}
}
// 邮箱验证
if (isset($rule['email']) && $rule['email']) {
$emailError = $this->validateEmail($field, $value);
if ($emailError) {
$errors[] = $emailError;
}
}
// URL验证
if (isset($rule['url']) && $rule['url']) {
$urlError = $this->validateUrl($field, $value);
if ($urlError) {
$errors[] = $urlError;
}
}
// 日期验证
if (isset($rule['date']) && $rule['date']) {
$dateError = $this->validateDate($field, $value, $rule['format'] ?? 'Y-m-d');
if ($dateError) {
$errors[] = $dateError;
}
}
// 自定义验证
if (isset($rule['custom']) && is_callable($rule['custom'])) {
$customError = $rule['custom']($value, $data, $field);
if ($customError) {
$errors[] = $customError;
}
}
return $errors;
}
/**
* 类型验证
*/
protected function validateType(string $field, mixed $value, string $type): ?string
{
switch ($type) {
case 'int':
case 'integer':
if (!is_int($value) && !ctype_digit((string)$value)) {
return "字段 {$field} 必须是整数";
}
break;
case 'float':
case 'double':
if (!is_float($value) && !is_numeric($value)) {
return "字段 {$field} 必须是数字";
}
break;
case 'string':
if (!is_string($value)) {
return "字段 {$field} 必须是字符串";
}
break;
case 'bool':
case 'boolean':
if (!is_bool($value) && !in_array($value, [0, 1, '0', '1', 'true', 'false'])) {
return "字段 {$field} 必须是布尔值";
}
break;
case 'array':
if (!is_array($value)) {
return "字段 {$field} 必须是数组";
}
break;
case 'date':
if (!($value instanceof \DateTime) && !strtotime($value)) {
return "字段 {$field} 必须是有效日期";
}
break;
}
return null;
}
/**
* 最小长度验证
*/
protected function validateMin(string $field, mixed $value, int $min): ?string
{
$length = is_array($value) ? count($value) : strlen((string)$value);
if ($length < $min) {
return "字段 {$field} 长度不能少于 {$min}";
}
return null;
}
/**
* 最大长度验证
*/
protected function validateMax(string $field, mixed $value, int $max): ?string
{
$length = is_array($value) ? count($value) : strlen((string)$value);
if ($length > $max) {
return "字段 {$field} 长度不能超过 {$max}";
}
return null;
}
/**
* 最小值验证
*/
protected function validateMinValue(string $field, mixed $value, int|float $min): ?string
{
if (!is_numeric($value) || $value < $min) {
return "字段 {$field} 值不能小于 {$min}";
}
return null;
}
/**
* 最大值验证
*/
protected function validateMaxValue(string $field, mixed $value, int|float $max): ?string
{
if (!is_numeric($value) || $value > $max) {
return "字段 {$field} 值不能大于 {$max}";
}
return null;
}
/**
* 正则表达式验证
*/
protected function validatePattern(string $field, mixed $value, string $pattern): ?string
{
if (!preg_match($pattern, (string)$value)) {
return "字段 {$field} 格式不正确";
}
return null;
}
/**
* 枚举值验证
*/
protected function validateEnum(string $field, mixed $value, array $enum): ?string
{
if (!in_array($value, $enum)) {
return "字段 {$field} 值必须是: " . implode(', ', $enum);
}
return null;
}
/**
* 邮箱验证
*/
protected function validateEmail(string $field, mixed $value): ?string
{
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
return "字段 {$field} 必须是有效邮箱地址";
}
return null;
}
/**
* URL验证
*/
protected function validateUrl(string $field, mixed $value): ?string
{
if (!filter_var($value, FILTER_VALIDATE_URL)) {
return "字段 {$field} 必须是有效URL";
}
return null;
}
/**
* 日期验证
*/
protected function validateDate(string $field, mixed $value, string $format): ?string
{
if ($value instanceof \DateTime) {
return null;
}
$date = \DateTime::createFromFormat($format, $value);
if (!$date || $date->format($format) !== $value) {
return "字段 {$field} 必须是有效日期,格式: {$format}";
}
return null;
}
/**
* 创建验证规则
*/
protected function rule(string $type = 'string', bool $required = false): array
{
return [
'type' => $type,
'required' => $required
];
}
/**
* 添加必填规则
*/
protected function required(string $message = null): array
{
return [
'required' => true,
'message' => $message
];
}
/**
* 添加长度规则
*/
protected function length(int $min = null, int $max = null, string $message = null): array
{
$rule = [];
if ($min !== null) {
$rule['min'] = $min;
}
if ($max !== null) {
$rule['max'] = $max;
}
if ($message) {
$rule['message'] = $message;
}
return $rule;
}
/**
* 添加数值范围规则
*/
protected function range(int|float $min = null, int|float $max = null, string $message = null): array
{
$rule = [];
if ($min !== null) {
$rule['min_value'] = $min;
}
if ($max !== null) {
$rule['max_value'] = $max;
}
if ($message) {
$rule['message'] = $message;
}
return $rule;
}
/**
* 添加正则表达式规则
*/
protected function pattern(string $regex, string $message = null): array
{
return [
'pattern' => $regex,
'message' => $message ?? '格式不正确'
];
}
/**
* 添加枚举规则
*/
protected function enum(array $values, string $message = null): array
{
return [
'enum' => $values,
'message' => $message ?? '值必须在指定范围内'
];
}
/**
* 添加邮箱规则
*/
protected function email(string $message = null): array
{
return [
'email' => true,
'message' => $message ?? '必须是有效邮箱地址'
];
}
/**
* 添加URL规则
*/
protected function url(string $message = null): array
{
return [
'url' => true,
'message' => $message ?? '必须是有效URL'
];
}
/**
* 添加日期规则
*/
protected function date(string $format = 'Y-m-d', string $message = null): array
{
return [
'date' => true,
'format' => $format,
'message' => $message ?? "必须是有效日期,格式: {$format}"
];
}
/**
* 添加自定义验证规则
*/
protected function custom(callable $callback, string $message = null): array
{
return [
'custom' => $callback,
'message' => $message
];
}
}