Skip to content

验证器.是否可接受的

Uses

php
<?php

use Leevel\Di\Container;
use Leevel\Kernel\Utils\Api;
use Leevel\Validate\IValidator;
use Leevel\Validate\UniqueRule;
use Leevel\Validate\Validator;
use Tests\Database\DatabaseTestCase as TestCase;
use Tests\Database\Ddd\Entity\CompositeId;
use Tests\Database\Ddd\Entity\Guestbook;

唯一值基本使用方法

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

php
# Leevel\Validate\UniqueRule::rule
/**
 * 创建语法规则.
 *
 * @throws \InvalidArgumentException
 */
public static function rule(string $entity, ?string $field = null, mixed $exceptId = null, ?string $primaryKey = null, array $additional = []): string;
  • entity 实体
  • field 指定数据库字段,未指定默认为待验证的字段作为数据库字段
  • exceptId 排除主键,一般用于编辑数据项校验
  • primaryKey 指定主键
  • additional 附加查询条件,成对出现

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

php
public function testBaseUse(): void
{
    $validate = new Validator(
        [
            'name' => 'foo',
        ],
        [
            'name' => $rule = UniqueRule::rule(Guestbook::class, exceptId: 1),
        ]
    );

    self::assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,_,:int:1,_', $rule);
    self::assertTrue($validate->success());

    $sql = $this->getLastSql('guest_book');
    $sqlResult = "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)";
    self::assertSame($sql, $sqlResult);
}

排除主键

php
public function testValidateWithExceptId(): void
{
    $validate = new Validator(
        [
            'name' => 'foo',
        ],
        [
            'name' => $rule = UniqueRule::rule(Guestbook::class, exceptId: 1),
        ]
    );

    self::assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,_,:int:1,_', $rule);
    self::assertTrue($validate->success());
    $sql = $this->getLastSql('guest_book');
    $sqlResult = "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)";
    self::assertSame($sql, $sqlResult);

    $connect = $this->createDatabaseConnect();

    self::assertSame(
        1,
        $connect
            ->table('guest_book')
            ->insert([
                'name' => 'foo',
                'content' => '',
            ]),
    );

    self::assertTrue($validate->success());
}

排除主键,并且指定主键

php
public function testValidateWithExceptIdAndPrimaryKey(): void
{
    $validate = new Validator(
        [
            'name' => 'foo',
        ],
        [
            'name' => $rule = UniqueRule::rule(Guestbook::class, null, 1, 'id'),
        ]
    );

    self::assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,_,:int:1,id', $rule);
    self::assertTrue($validate->success());
    $sql = $this->getLastSql('guest_book');
    $sqlResult = "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)";
    self::assertSame($sql, $sqlResult);

    $connect = $this->createDatabaseConnect();

    self::assertSame(
        1,
        $connect
            ->table('guest_book')
            ->insert([
                'name' => 'foo',
                'content' => '',
            ]),
    );

    self::assertTrue($validate->success());
}

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

php
public function testValidateWithExceptIdAndCompositeIdAndIgnore(): void
{
    $validate = new Validator(
        [
            'name' => 'foo',
        ],
        [
            'name' => $rule = UniqueRule::rule(CompositeId::class, exceptId: 1),
        ]
    );

    self::assertSame('unique:Tests\\Database\\Ddd\\Entity\\CompositeId,_,:int:1,_', $rule);
    self::assertTrue($validate->success());
    $sql = $this->getLastSql('composite_id');
    $sqlResult = "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)";
    self::assertSame($sql, $sqlResult);

    $connect = $this->createDatabaseConnect();

    $connect
        ->table('composite_id')
        ->insert([
            'id1' => 1,
            'id2' => 2,
            'name' => '',
        ])
    ;

    self::assertTrue($validate->success());
}

不排除主键

php
public function testValidateWithoutExceptId(): void
{
    $validate = new Validator(
        [
            'name' => 'foo',
        ],
        [
            'name' => $rule = UniqueRule::rule(Guestbook::class),
        ]
    );

    self::assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,_,_,_', $rule);
    self::assertTrue($validate->success());
    $sql = $this->getLastSql('guest_book');
    $sqlResult = "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)";
    self::assertSame($sql, $sqlResult);

    $connect = $this->createDatabaseConnect();

    self::assertSame(
        1,
        $connect
            ->table('guest_book')
            ->insert([
                'name' => 'foo',
                'content' => '',
            ]),
    );

    self::assertFalse($validate->success());
}

unique 参数缺失

php
public function testCheckParamLengthException(): void
{
    $this->expectException(\InvalidArgumentException::class);
    $this->expectExceptionMessage(
        'Missing the first element of param.'
    );

    $validate = new Validator(
        [
            'name' => 'foo',
        ],
        [
            'name' => 'unique',
        ]
    );

    $validate->success();
}

指定验证数据库字段

php
public function testValidateWithValidateField(): void
{
    $validate = new Validator(
        [
            'name' => 'foo',
        ],
        [
            'name' => $rule = UniqueRule::rule(Guestbook::class, 'name', 1),
        ]
    );

    self::assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,name,:int:1,_', $rule);
    self::assertTrue($validate->success());
    $sql = $this->getLastSql('guest_book');
    $sqlResult = "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)";
    self::assertSame($sql, $sqlResult);

    $connect = $this->createDatabaseConnect();

    self::assertSame(
        1,
        $connect
            ->table('guest_book')
            ->insert([
                'name' => 'foo',
                'content' => '',
            ]),
    );

    self::assertTrue($validate->success());
}

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

php
public function testValidateWithValidateMultiField(): void
{
    $validate = new Validator(
        [
            'name' => 'foo',
        ],
        [
            'name' => $rule = UniqueRule::rule(Guestbook::class, 'name:content', 1),
        ]
    );

    self::assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,name:content,:int:1,_', $rule);
    self::assertTrue($validate->success());
    $sql = $this->getLastSql('guest_book');
    $sqlResult = "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)";
    self::assertSame($sql, $sqlResult);

    $connect = $this->createDatabaseConnect();

    self::assertSame(
        1,
        $connect
            ->table('guest_book')
            ->insert([
                'name' => 'foo',
                'content' => '',
            ]),
    );

    self::assertTrue($validate->success());
}

带附加条件

php
public function testValidateWithParseAdditional(): void
{
    $validate = new Validator(
        [
            'name' => 'foo',
        ],
        [
            'name' => $rule = UniqueRule::rule(Guestbook::class, additional: ['id' => '1']),
        ]
    );

    self::assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,_,_,_,id,:string:1', $rule);
    self::assertTrue($validate->success());
    $sql = $this->getLastSql('guest_book');
    $sqlResult = "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)";
    self::assertSame($sql, $sqlResult);

    $connect = $this->createDatabaseConnect();

    self::assertSame(
        1,
        $connect
            ->table('guest_book')
            ->insert([
                'name' => 'foo',
                'content' => '',
            ]),
    );

    self::assertFalse($validate->success());
}

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

php
public function testValidateWithParseAdditionalCustomOperate(): void
{
    $validate = new Validator(
        [
            'name' => 'foo',
        ],
        [
            'name' => $rule = UniqueRule::rule(Guestbook::class, additional: ['id:>' => '1']),
        ]
    );

    self::assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,_,_,_,id:>,:string:1', $rule);
    self::assertTrue($validate->success());
    $sql = $this->getLastSql('guest_book');
    $sqlResult = "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)";
    self::assertSame($sql, $sqlResult);

    $connect = $this->createDatabaseConnect();

    self::assertSame(
        1,
        $connect
            ->table('guest_book')
            ->insert([
                'name' => 'foo',
                'content' => '',
            ]),
    );

    self::assertTrue($validate->success());
}

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

php
public function testValidateWithStringFloatAndStringInt(): void
{
    $validate = new Validator(
        [
            'name' => 'foo',
        ],
        [
            'name' => $rule = UniqueRule::rule(Guestbook::class, 'name', '1', additional: ['content' => '1.5']),
        ]
    );

    self::assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,name,:string:1,_,content,:string:1.5', $rule);
    self::assertTrue($validate->success());

    $sql = $this->getLastSql('guest_book');
    $sqlResult = "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)";
    self::assertSame($sql, $sqlResult);
}

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

php
public function testValidateWithFloatAndInt(): void
{
    $validate = new Validator(
        [
            'name' => 'foo',
        ],
        [
            'name' => $rule = UniqueRule::rule(Guestbook::class, 'name', 1, additional: ['content' => 1.5]),
        ]
    );

    self::assertSame('unique:Tests\\Database\\Ddd\\Entity\\Guestbook,name,:int:1,_,content,:float:1.5', $rule);
    self::assertTrue($validate->success());
    $sql = $this->getLastSql('guest_book');
    $sqlResult = "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)";
    self::assertSame($sql, $sqlResult);
}