验证器.是否可接受的

Testing Is Documentation

tests/Validate/Validator/UniqueTest.php验证器.是否可接受的 - 图1

Uses

  1. <?php
  2. use Leevel\Di\Container;
  3. use Leevel\Validate\IValidator;
  4. use Leevel\Validate\UniqueRule;
  5. use Leevel\Validate\Validator;
  6. use Tests\Database\DatabaseTestCase as TestCase;
  7. use Tests\Database\Ddd\Entity\CompositeId;
  8. use Tests\Database\Ddd\Entity\Guestbook;

唯一值基本使用方法

框架提供了一个唯一值创建生成规则方法

  1. \Leevel\Validate\UniqueRule::rule(string $entity, ?string $field = null, $exceptId = null, ?string $primaryKey = null, ...$additional): string;
  • entity 实体
  • field 指定数据库字段,未指定默认为待验证的字段作为数据库字段
  • exceptId 排除主键,一般用于编辑数据项校验
  • primaryKey 指定主键
  • additional 附加查询条件,成对出现

唯一值是一个非常常用的功能,框架强化了这一功能。

  1. public function testBaseUse(): void
  2. {
  3. $validate = new Validator(
  4. [
  5. 'name' => 'foo',
  6. ],
  7. [
  8. 'name' => $rule = UniqueRule::rule(Guestbook::class, null, 1),
  9. ]
  10. );
  11. $this->assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,_,__int@1,_', $rule);
  12. $this->assertTrue($validate->success());
  13. $sql = $this->getLastSql('guest_book');
  14. $this->assertSame($sql, "SQL: [139] SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = :guest_book_name AND `guest_book`.`id` <> :guest_book_id LIMIT 1 | Params: 2 | Key: Name: [16] :guest_book_name | paramno=0 | name=[16] \":guest_book_name\" | is_param=1 | param_type=2 | Key: Name: [14] :guest_book_id | paramno=1 | name=[14] \":guest_book_id\" | is_param=1 | param_type=1 (SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = 'foo' AND `guest_book`.`id` <> 1 LIMIT 1)");
  15. }

排除主键

  1. public function testValidateWithExceptId(): void
  2. {
  3. $validate = new Validator(
  4. [
  5. 'name' => 'foo',
  6. ],
  7. [
  8. 'name' => $rule = UniqueRule::rule(Guestbook::class, null, 1),
  9. ]
  10. );
  11. $this->assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,_,__int@1,_', $rule);
  12. $this->assertTrue($validate->success());
  13. $sql = $this->getLastSql('guest_book');
  14. $this->assertSame($sql, "SQL: [139] SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = :guest_book_name AND `guest_book`.`id` <> :guest_book_id LIMIT 1 | Params: 2 | Key: Name: [16] :guest_book_name | paramno=0 | name=[16] \":guest_book_name\" | is_param=1 | param_type=2 | Key: Name: [14] :guest_book_id | paramno=1 | name=[14] \":guest_book_id\" | is_param=1 | param_type=1 (SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = 'foo' AND `guest_book`.`id` <> 1 LIMIT 1)");
  15. $connect = $this->createDatabaseConnect();
  16. $this->assertSame(
  17. 1,
  18. $connect
  19. ->table('guest_book')
  20. ->insert([
  21. 'name' => 'foo',
  22. 'content' => '',
  23. ]),
  24. );
  25. $this->assertTrue($validate->success());
  26. }

排除主键,并且指定主键

  1. public function testValidateWithExceptIdAndPrimaryKey(): void
  2. {
  3. $validate = new Validator(
  4. [
  5. 'name' => 'foo',
  6. ],
  7. [
  8. 'name' => $rule = UniqueRule::rule(Guestbook::class, null, 1, 'id'),
  9. ]
  10. );
  11. $this->assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,_,__int@1,id', $rule);
  12. $this->assertTrue($validate->success());
  13. $sql = $this->getLastSql('guest_book');
  14. $this->assertSame($sql, "SQL: [139] SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = :guest_book_name AND `guest_book`.`id` <> :guest_book_id LIMIT 1 | Params: 2 | Key: Name: [16] :guest_book_name | paramno=0 | name=[16] \":guest_book_name\" | is_param=1 | param_type=2 | Key: Name: [14] :guest_book_id | paramno=1 | name=[14] \":guest_book_id\" | is_param=1 | param_type=1 (SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = 'foo' AND `guest_book`.`id` <> 1 LIMIT 1)");
  15. $connect = $this->createDatabaseConnect();
  16. $this->assertSame(
  17. 1,
  18. $connect
  19. ->table('guest_book')
  20. ->insert([
  21. 'name' => 'foo',
  22. 'content' => '',
  23. ]),
  24. );
  25. $this->assertTrue($validate->success());
  26. }

排除主键,复合主键将会被忽略

  1. public function testValidateWithExceptIdAndCompositeIdAndIgnore(): void
  2. {
  3. $validate = new Validator(
  4. [
  5. 'name' => 'foo',
  6. ],
  7. [
  8. 'name' => $rule = UniqueRule::rule(CompositeId::class, null, 1),
  9. ]
  10. );
  11. $this->assertSame('unique:Tests\\Database\\Ddd\\Entity\\CompositeId,_,__int@1,_', $rule);
  12. $this->assertTrue($validate->success());
  13. $sql = $this->getLastSql('composite_id');
  14. $this->assertSame($sql, "SQL: [105] SELECT COUNT(*) AS row_count FROM `composite_id` WHERE `composite_id`.`name` = :composite_id_name LIMIT 1 | Params: 1 | Key: Name: [18] :composite_id_name | paramno=0 | name=[18] \":composite_id_name\" | is_param=1 | param_type=2 (SELECT COUNT(*) AS row_count FROM `composite_id` WHERE `composite_id`.`name` = 'foo' LIMIT 1)");
  15. $connect = $this->createDatabaseConnect();
  16. $connect
  17. ->table('composite_id')
  18. ->insert([
  19. 'id1' => 1,
  20. 'id2' => 2,
  21. 'name' => '',
  22. ]);
  23. $this->assertTrue($validate->success());
  24. }

不排除主键

  1. public function testValidateWithoutExceptId(): void
  2. {
  3. $validate = new Validator(
  4. [
  5. 'name' => 'foo',
  6. ],
  7. [
  8. 'name' => $rule = UniqueRule::rule(Guestbook::class, null),
  9. ]
  10. );
  11. $this->assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,_,_,_', $rule);
  12. $this->assertTrue($validate->success());
  13. $sql = $this->getLastSql('guest_book');
  14. $this->assertSame($sql, "SQL: [99] SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = :guest_book_name LIMIT 1 | Params: 1 | Key: Name: [16] :guest_book_name | paramno=0 | name=[16] \":guest_book_name\" | is_param=1 | param_type=2 (SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = 'foo' LIMIT 1)");
  15. $connect = $this->createDatabaseConnect();
  16. $this->assertSame(
  17. 1,
  18. $connect
  19. ->table('guest_book')
  20. ->insert([
  21. 'name' => 'foo',
  22. 'content' => '',
  23. ]),
  24. );
  25. $this->assertFalse($validate->success());
  26. }

unique 参数缺失

  1. public function testCheckParamLengthException(): void
  2. {
  3. $this->expectException(\InvalidArgumentException::class);
  4. $this->expectExceptionMessage(
  5. 'Missing the first element of param.'
  6. );
  7. $validate = new Validator(
  8. [
  9. 'name' => 'foo',
  10. ],
  11. [
  12. 'name' => 'unique',
  13. ]
  14. );
  15. $validate->success();
  16. }

指定验证数据库字段

  1. public function testValidateWithValidateField(): void
  2. {
  3. $validate = new Validator(
  4. [
  5. 'name' => 'foo',
  6. ],
  7. [
  8. 'name' => $rule = UniqueRule::rule(Guestbook::class, 'name', 1),
  9. ]
  10. );
  11. $this->assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,name,__int@1,_', $rule);
  12. $this->assertTrue($validate->success());
  13. $sql = $this->getLastSql('guest_book');
  14. $this->assertSame($sql, "SQL: [139] SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = :guest_book_name AND `guest_book`.`id` <> :guest_book_id LIMIT 1 | Params: 2 | Key: Name: [16] :guest_book_name | paramno=0 | name=[16] \":guest_book_name\" | is_param=1 | param_type=2 | Key: Name: [14] :guest_book_id | paramno=1 | name=[14] \":guest_book_id\" | is_param=1 | param_type=1 (SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = 'foo' AND `guest_book`.`id` <> 1 LIMIT 1)");
  15. $connect = $this->createDatabaseConnect();
  16. $this->assertSame(
  17. 1,
  18. $connect
  19. ->table('guest_book')
  20. ->insert([
  21. 'name' => 'foo',
  22. 'content' => '',
  23. ]),
  24. );
  25. $this->assertTrue($validate->success());
  26. }

指定验证数据库字段,支持多个字段

  1. public function testValidateWithValidateMultiField(): void
  2. {
  3. $validate = new Validator(
  4. [
  5. 'name' => 'foo',
  6. ],
  7. [
  8. 'name' => $rule = UniqueRule::rule(Guestbook::class, 'name:content', 1),
  9. ]
  10. );
  11. $this->assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,name:content,__int@1,_', $rule);
  12. $this->assertTrue($validate->success());
  13. $sql = $this->getLastSql('guest_book');
  14. $this->assertSame($sql, "SQL: [188] SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = :guest_book_name AND `guest_book`.`content` = :guest_book_content AND `guest_book`.`id` <> :guest_book_id LIMIT 1 | Params: 3 | Key: Name: [16] :guest_book_name | paramno=0 | name=[16] \":guest_book_name\" | is_param=1 | param_type=2 | Key: Name: [19] :guest_book_content | paramno=1 | name=[19] \":guest_book_content\" | is_param=1 | param_type=2 | Key: Name: [14] :guest_book_id | paramno=2 | name=[14] \":guest_book_id\" | is_param=1 | param_type=1 (SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = 'foo' AND `guest_book`.`content` = 'foo' AND `guest_book`.`id` <> 1 LIMIT 1)");
  15. $connect = $this->createDatabaseConnect();
  16. $this->assertSame(
  17. 1,
  18. $connect
  19. ->table('guest_book')
  20. ->insert([
  21. 'name' => 'foo',
  22. 'content' => '',
  23. ]),
  24. );
  25. $this->assertTrue($validate->success());
  26. }

带附加条件

  1. public function testValidateWithParseAdditional(): void
  2. {
  3. $validate = new Validator(
  4. [
  5. 'name' => 'foo',
  6. ],
  7. [
  8. 'name' => $rule = UniqueRule::rule(Guestbook::class, null, null, null, 'id', '1'),
  9. ]
  10. );
  11. $this->assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,_,_,_,id,__string@1', $rule);
  12. $this->assertTrue($validate->success());
  13. $sql = $this->getLastSql('guest_book');
  14. $this->assertSame($sql, "SQL: [138] SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = :guest_book_name AND `guest_book`.`id` = :guest_book_id LIMIT 1 | Params: 2 | Key: Name: [16] :guest_book_name | paramno=0 | name=[16] \":guest_book_name\" | is_param=1 | param_type=2 | Key: Name: [14] :guest_book_id | paramno=1 | name=[14] \":guest_book_id\" | is_param=1 | param_type=2 (SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = 'foo' AND `guest_book`.`id` = '1' LIMIT 1)");
  15. $connect = $this->createDatabaseConnect();
  16. $this->assertSame(
  17. 1,
  18. $connect
  19. ->table('guest_book')
  20. ->insert([
  21. 'name' => 'foo',
  22. 'content' => '',
  23. ]),
  24. );
  25. $this->assertFalse($validate->success());
  26. }

带附加条件,附加条件支持表达式

  1. public function testValidateWithParseAdditionalCustomOperate(): void
  2. {
  3. $validate = new Validator(
  4. [
  5. 'name' => 'foo',
  6. ],
  7. [
  8. 'name' => $rule = UniqueRule::rule(Guestbook::class, null, null, null, 'id:>', '1'),
  9. ]
  10. );
  11. $this->assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,_,_,_,id:>,__string@1', $rule);
  12. $this->assertTrue($validate->success());
  13. $sql = $this->getLastSql('guest_book');
  14. $this->assertSame($sql, "SQL: [138] SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = :guest_book_name AND `guest_book`.`id` > :guest_book_id LIMIT 1 | Params: 2 | Key: Name: [16] :guest_book_name | paramno=0 | name=[16] \":guest_book_name\" | is_param=1 | param_type=2 | Key: Name: [14] :guest_book_id | paramno=1 | name=[14] \":guest_book_id\" | is_param=1 | param_type=2 (SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = 'foo' AND `guest_book`.`id` > '1' LIMIT 1)");
  15. $connect = $this->createDatabaseConnect();
  16. $this->assertSame(
  17. 1,
  18. $connect
  19. ->table('guest_book')
  20. ->insert([
  21. 'name' => 'foo',
  22. 'content' => '',
  23. ]),
  24. );
  25. $this->assertTrue($validate->success());
  26. }

带附加条件,附加条件区分整数和浮点数的字符串

  1. public function testValidateWithStringFloatAndStringInt(): void
  2. {
  3. $validate = new Validator(
  4. [
  5. 'name' => 'foo',
  6. ],
  7. [
  8. 'name' => $rule = UniqueRule::rule(Guestbook::class, 'name', '1', null, 'content', '1.5'),
  9. ]
  10. );
  11. $this->assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,name,__string@1,_,content,__string@1.5', $rule);
  12. $this->assertTrue($validate->success());
  13. $sql = $this->getLastSql('guest_book');
  14. $this->assertSame($sql, "SQL: [188] SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = :guest_book_name AND `guest_book`.`id` <> :guest_book_id AND `guest_book`.`content` = :guest_book_content LIMIT 1 | Params: 3 | Key: Name: [16] :guest_book_name | paramno=0 | name=[16] \":guest_book_name\" | is_param=1 | param_type=2 | Key: Name: [14] :guest_book_id | paramno=1 | name=[14] \":guest_book_id\" | is_param=1 | param_type=2 | Key: Name: [19] :guest_book_content | paramno=2 | name=[19] \":guest_book_content\" | is_param=1 | param_type=2 (SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = 'foo' AND `guest_book`.`id` <> '1' AND `guest_book`.`content` = '1.5' LIMIT 1)");
  15. }

带附加条件,附加条件为整数和浮点数

  1. public function testValidateWithFloatAndInt(): void
  2. {
  3. $validate = new Validator(
  4. [
  5. 'name' => 'foo',
  6. ],
  7. [
  8. 'name' => $rule = UniqueRule::rule(Guestbook::class, 'name', 1, null, 'content', 1.5),
  9. ]
  10. );
  11. $this->assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,name,__int@1,_,content,__float@1.5', $rule);
  12. $this->assertTrue($validate->success());
  13. $sql = $this->getLastSql('guest_book');
  14. $this->assertSame($sql, "SQL: [188] SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = :guest_book_name AND `guest_book`.`id` <> :guest_book_id AND `guest_book`.`content` = :guest_book_content LIMIT 1 | Params: 3 | Key: Name: [16] :guest_book_name | paramno=0 | name=[16] \":guest_book_name\" | is_param=1 | param_type=2 | Key: Name: [14] :guest_book_id | paramno=1 | name=[14] \":guest_book_id\" | is_param=1 | param_type=1 | Key: Name: [19] :guest_book_content | paramno=2 | name=[19] \":guest_book_content\" | is_param=1 | param_type=2 (SELECT COUNT(*) AS row_count FROM `guest_book` WHERE `guest_book`.`name` = 'foo' AND `guest_book`.`id` <> 1 AND `guest_book`.`content` = 1.5 LIMIT 1)");
  15. }