EnumUtil.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <?php
  2. namespace app\utils;
  3. use ReflectionClass;
  4. use ReflectionException;
  5. /**
  6. * 智能枚举验证器
  7. * 自动发现并验证请求参数中的枚举字段
  8. */
  9. class EnumUtil
  10. {
  11. /**
  12. * 自动验证请求参数中的枚举字段
  13. *
  14. * @param string|object $enumClassOrInstance 枚举类名或实例
  15. * @param array $requestData 请求数据
  16. * @return array 验证结果 ['valid' => bool, 'errors' => array]
  17. */
  18. public static function autoValidate($enumClassOrInstance, array $requestData): array
  19. {
  20. $errors = [];
  21. try {
  22. $constants = self::getEnumConstants($enumClassOrInstance);
  23. foreach ($constants as $constName => $enumValues) {
  24. if (!self::isValidEnumArray($enumValues)) {
  25. continue;
  26. }
  27. $fieldName = self::constToFieldName($constName);
  28. if (array_key_exists($fieldName, $requestData)) {
  29. $result = self::validateEnumValue($requestData[$fieldName], $enumValues, $constName);
  30. if (!$result['valid']) {
  31. $errors[] = $result['error'];
  32. }
  33. }
  34. }
  35. } catch (ReflectionException $e) {
  36. return [
  37. 'valid' => false,
  38. 'errors' => ["枚举验证异常: " . $e->getMessage()]
  39. ];
  40. }
  41. return empty($errors) ? [
  42. 'valid' => true,
  43. 'errors' => []
  44. ] : [
  45. 'valid' => false,
  46. 'errors' => $errors
  47. ];
  48. }
  49. /**
  50. * 获取枚举类的所有字段映射
  51. *
  52. * @param string|object $enumClassOrInstance 枚举类名或实例
  53. * @return array 字段映射 [字段名 => 枚举值数组]
  54. */
  55. public static function getFieldMappings($enumClassOrInstance): array
  56. {
  57. $mappings = [];
  58. try {
  59. $constants = self::getEnumConstants($enumClassOrInstance);
  60. foreach ($constants as $constName => $enumValues) {
  61. if (self::isValidEnumArray($enumValues)) {
  62. $mappings[self::constToFieldName($constName)] = $enumValues;
  63. }
  64. }
  65. } catch (ReflectionException $e) {
  66. // 忽略异常,返回空数组
  67. }
  68. return $mappings;
  69. }
  70. /**
  71. * 获取枚举类的常量
  72. *
  73. * @param string|object $enumClassOrInstance
  74. * @return array
  75. * @throws ReflectionException
  76. */
  77. private static function getEnumConstants($enumClassOrInstance): array
  78. {
  79. return (new ReflectionClass($enumClassOrInstance))->getConstants();
  80. }
  81. /**
  82. * 检查是否为有效的枚举数组(非MAP格式的数组)
  83. *
  84. * @param mixed $enumValues
  85. * @return bool
  86. */
  87. private static function isValidEnumArray($enumValues): bool
  88. {
  89. return is_array($enumValues) && !empty($enumValues) && !self::isMapFormat($enumValues);
  90. }
  91. /**
  92. * 将枚举常量名转换为字段名
  93. *
  94. * @param string $constName 常量名称
  95. * @return string 字段名
  96. */
  97. private static function constToFieldName(string $constName): string
  98. {
  99. return strtolower($constName);
  100. }
  101. /**
  102. * 验证单个枚举值
  103. *
  104. * @param mixed $value 要验证的值
  105. * @param array $enumValues 枚举值数组
  106. * @param string $constName 常量名称
  107. * @return array 验证结果 ['valid' => bool, 'error' => string|null]
  108. */
  109. private static function validateEnumValue($value, array $enumValues, string $constName): array
  110. {
  111. $validValues = array_keys($enumValues);
  112. $normalizedValue = is_numeric($value) ? (int)$value : $value;
  113. if (!in_array($normalizedValue, $validValues, true)) {
  114. return [
  115. 'valid' => false,
  116. 'error' => self::constToFieldName($constName) . "参数错误,值:{$value}"
  117. ];
  118. }
  119. return [
  120. 'valid' => true,
  121. 'error' => null
  122. ];
  123. }
  124. /**
  125. * 检查枚举值数组是否为MAP格式(包含code字段)
  126. *
  127. * @param array $enumValues 枚举值数组
  128. * @return bool
  129. */
  130. private static function isMapFormat(array $enumValues): bool
  131. {
  132. if (empty($enumValues)) {
  133. return false;
  134. }
  135. $firstValue = reset($enumValues);
  136. return is_array($firstValue) && isset($firstValue['code']);
  137. }
  138. }