验证器

imi 提供了基本数据类型的验证,以及可扩展的验证方法,这一切都可以通过注解来使用。

注解

@Condition

通用验证条件,传入回调进行验证

该注解可以写在类、属性、方法上。

参数:

  1. /**
  2. * 参数名称
  3. * 属性注解可省略
  4. *
  5. * @var string
  6. */
  7. public $name;
  8. /**
  9. * 当值不符合条件时的默认值
  10. *
  11. * @var mixed
  12. */
  13. public $default;
  14. /**
  15. * 对结果取反
  16. *
  17. * @var boolean
  18. */
  19. public $inverseResult = false;
  20. /**
  21. * 当验证条件不符合时的信息
  22. *
  23. * 支持代入{:value}原始值
  24. * 支持代入{:data.xxx}所有数据中的某项
  25. * 支持以{name}这样的形式,代入注解参数值
  26. *
  27. * @var string
  28. */
  29. public $message = '{name} validate failed';
  30. /**
  31. * 验证回调
  32. *
  33. * @var callable
  34. */
  35. public $callable;
  36. /**
  37. * 参数名数组
  38. *
  39. * 支持代入{:value}原始值
  40. * 支持代入{:data}所有数据
  41. * 支持代入{:data.xxx}所有数据中的某项
  42. * 支持以{name}这样的形式,代入注解参数值
  43. * 如果没有{},则原样传值
  44. *
  45. * @var array
  46. */
  47. public $args = ['{:value}'];
  48. /**
  49. * 异常类
  50. *
  51. * @var string
  52. */
  53. public $exception = null;
  54. /**
  55. * 异常编码
  56. *
  57. * @var integer
  58. */
  59. public $exCode = null;

callable 是验证回调,支持:

  • "is_int"
  • "XXX::check"
  • {@Inject("BeanName"), "methodName"}
  • {"$this", "methodName"}指定当前对象中的方法,但Http验证器中无法使用。
  • 方法必须是publicprotected

args 是回调方法参数,例子:

  1. class TestValidate
  2. {
  3. public $abc = 'imi niubi!';
  4. /**
  5. * @AutoValidation
  6. * @Condition(name="argName", @callable({"$this", "validate"}), args={"{:value}", "{:data}", "{name}", "{:data.a}", {":data.$this.abc"}})
  7. */
  8. public function test($a, $b)
  9. {
  10. }
  11. /**
  12. * 本方法参数,由 @Condition 的 args 决定
  13. * $value 是当前验证参数对应的值,也就是 test() 方法中,$a 参数值
  14. * $data 是集合了 test() 方法中所有参数的数组
  15. * 你可以用 $data['b'] 获取 $b 参数值
  16. * $name 代表是 @Condition 中的 name 参数,同理可以取到注解中的其它参数值
  17. * $a 就是指定传入 test() 方法中 $a 参数值
  18. * $vvv 就是指定 test() 方法所在类对象中的 $abc 属性值
  19. */
  20. public function validate($value, $data, $name, $a, $vvv)
  21. {
  22. var_dump($value, $data, $name, $a, $vvv);
  23. return true;
  24. }
  25. }

inverseResult 参数为true时,会对验证回调方法结果取反后,判断是否为true

message 是验证失败的消息,可以将{name}形式的注解参数值代入,也可以使用{:value}代入验证值。

exceptionexCode可以设定验证失败时抛出的异常类及异常编码,默认为\InvalidArgumentException类。

除了callableargs以外,其它参数都可以作为其它验证条件注解(如:@Required 等)的参数

@Required

判断值是否存在

@Text

文本验证

必须>=6位长度,最长不限制:

@Text(min=6)

长度必须>=6 && <=12:

@Text(min=6, max=12)

@Integer

整数验证

验证必须为整数:

@Integer

验证必须为>=1024的整数:

@Integer(min=1024)

验证必须为<=1024的整数:

@Integer(max=1024)

验证必须为>=1 && <=10的整数:

@Integer(min=1, max=10)

@Decimal

小数验证

验证必须为小数:

@Decimal

验证必须为>=10.24的小数:

@Decimal(min=10.24)

验证必须为<=10.24的小数:

@Decimal(max=10.24)

验证必须为>=1 && <=10.24的小数:

@Decimal(min=1, max=10.24)

传入1,结果为false

传入1.0,结果为true

@Number

数值验证,允许是整数或者小数

验证必须为数值:

@Decimal

验证必须为>=10.24的数值:

@Decimal(min=10.24)

验证必须为<=10.24的数值:

@Decimal(max=10.24)

验证必须为>=1 && <=10.24的数值:

@Decimal(min=1, max=10.24)

传入1,结果为true

传入1.0,结果为true

@InList

列表验证,判断值是否存在于列表中

@InList(list={1, 2, 3})

相当于:

  1. $result = in_array($value, [1, 2, 3]);

@Compare

比较验证注解

@Compare(name="参数名", value="被比较值", operation="比较符,如:==")

value 可以直接传值,也可以配合 @ValidateValue 注解使用。

operation 允许使用:==、!=、===、!==、<、<=、>、>=

@ValidateValue

指定验证时的值注解

@Compare(name="id", value=@ValidateValue("{:data.id}"), operation="==")

@InEnum

用于验证值是否存在于枚举列表中

@InEnum(name="type", enum="EnumClass")

自动验证

注解:@AutoValidation

验证类属性

imi 支持在类、属性上使用 @AutoValidation 注解,当构造方法执行完毕后,触发验证。验证失败抛出异常。

如下代码,写在类上的注解以及属性上的注解,都因为加了@AutoValidation 注解,所以在构造方法执行完成后,会自动进行验证,验证失败则抛出异常。

  1. /**
  2. * @Bean("ValidatorTest")
  3. *
  4. * @AutoValidation
  5. *
  6. *
  7. * @InList(name="in", list={1, 2, 3}, message="{:value} 不在列表内")
  8. * @Integer(name="int", min=0, max=100, message="{:value} 不符合大于等于{min}且小于等于{max}")
  9. * @Required(name="required", message="{name}为必须参数")
  10. * @Number(name="number", min=0.01, max=999.99, accuracy=2, message="数值必须大于等于{min},小于等于{max},小数点最多保留{accuracy}位小数,当前值为{:value}")
  11. * @Text(name="text", min=6, max=12, message="{name}参数长度必须>={min} && <={max}")
  12. * @Condition(name="my", callable="\ImiDemo\HttpDemo\MainServer\Validator\Test::myValidate", args={"{:value}"}, message="{name}值必须为1")
  13. */
  14. class Test
  15. {
  16. /**
  17. * @Decimal(min=-0.01, max=999.99, accuracy=2, message="小数必须大于等于{min},小于等于{max},小数点最多保留{accuracy}位小数,当前值为{:value}")
  18. *
  19. * @var float
  20. */
  21. public $decimal;
  22. public function __construct($data = [], $rules = null)
  23. {
  24. foreach($data as $name => $value)
  25. {
  26. $this->$name = $value;
  27. }
  28. }
  29. public static function myValidate($value)
  30. {
  31. return 1 == $value;
  32. }
  33. }

验证方法参数

在 imi 中,如果你在方法上使用 @AutoValidation 注解,当方法被调用前,会触发验证操作,验证失败则抛出异常。验证的参数是传入方法的参数,如下代码,验证通过则进入方法体中,验证失败会抛出异常。

  1. /**
  2. * @AutoValidation
  3. *
  4. * @Required(name="id", message="用户ID为必传参数")
  5. * @Integer(name="id", min="1", message="用户ID不符合规则")
  6. * @Required(name="name", message="用户姓名为必传参数")
  7. * @Text(name="name", min="2", message="用户姓名长度不得少于2位")
  8. *
  9. * @param int $id
  10. * @param string $name
  11. * @return void
  12. */
  13. public function test222($id, $name)
  14. {
  15. var_dump($id, $name);
  16. }

手动验证

你也可以自己定义一个专门用于验证的类,将数据传入该类,手动调用验证方法。

  1. /**
  2. * @Bean("ValidatorTest")
  3. *
  4. * @InList(name="in", list={1, 2, 3}, message="{:value} 不在列表内")
  5. * @Integer(name="int", min=0, max=100, message="{:value} 不符合大于等于{min}且小于等于{max}")
  6. * @Required(name="required", message="{name}为必须参数")
  7. * @Number(name="number", min=0.01, max=999.99, accuracy=2, message="数值必须大于等于{min},小于等于{max},小数点最多保留{accuracy}位小数,当前值为{:value}")
  8. * @Text(name="text", min=6, max=12, message="{name}参数长度必须>={min} && <={max}")
  9. * @Condition(name="my", callable="\ImiDemo\HttpDemo\MainServer\Validator\Test::myValidate", args={"{:value}"}, message="{name}值必须为1")
  10. */
  11. class Test extends Validator
  12. {
  13. /**
  14. * @Decimal(min=-0.01, max=999.99, accuracy=2, message="小数必须大于等于{min},小于等于{max},小数点最多保留{accuracy}位小数,当前值为{:value}")
  15. *
  16. * @var float
  17. */
  18. public $decimal;
  19. public function __construct($data = [], $rules = null)
  20. {
  21. parent::__construct($data, $rules);
  22. foreach($data as $name => $value)
  23. {
  24. $this->$name = $value;
  25. }
  26. }
  27. public static function myValidate($value)
  28. {
  29. return 1 == $value;
  30. }
  31. }

当你使用手动验证时,可以直接new出来使用,不是很有必要使用容器。

使用代码示例:

  1. $v = new Test([
  2. // 'decimal' => 1.1,
  3. // 'in' => 1,
  4. 'int' => 1,
  5. 'required' => 1,
  6. 'number' => 1,
  7. 'my' => 1,
  8. ]);
  9. // 也可以设置数据
  10. // $v->setData([]);
  11. // 验证,当遇到不通过时结束验证流程
  12. $result = $v->validate();
  13. if(!$result)
  14. {
  15. echo 'error: ', $v->getMessage(), PHP_EOL;
  16. // 当前错误的注解规则
  17. var_dump($v->getFailRule());
  18. }
  19. // 验证所有
  20. $result = $v->validateAll();
  21. if(!$result)
  22. {
  23. var_dump(
  24. // 所有错误数组,注意每个成员也是个数组,里面可能有多个
  25. $v->getResults()
  26. // 所有错误的注解规则
  27. , $v->getFailRules()
  28. );
  29. }
  30. // 获得数据,如果你配置有default属性,并且验证失败,可以获得默认值
  31. $data = $v->getData();