respect/断言

将 Respect\Validation 的强大功能融入断言库

2.0.0 2023-04-11 21:30 UTC

This package is auto-updated.

Last update: 2024-09-12 00:54:44 UTC


README

Build Status Code Coverage Latest Stable Version Total Downloads License

Validation 的强大功能融入断言库。

  • 超过 1.5k 个断言
  • 支持自定义消息
  • 支持自定义异常

要查看断言的完整列表,请查看所有 mixin 接口,并阅读 Validation 了解每个规则/断言的工作方式。

安装

此包可在 Packagist 上找到,您可以使用 Composer 进行安装。

composer require respect/assertion

支持 PHP 8.1 或更高版本。

另一个断言库

PHP 社区中许多人使用的 PHP 断言库

它们都易于使用,并且有很多断言,因此没有必要再创建一个。另一方面,它们的断言比 Validation 少。

Validation 的主要思想是使其易于创建验证链,但当你想要进行简单的断言时,可能会变得啰嗦。

此库为 Validation 提供了一个更简单的断言 API,这意味着您可以使用所有 Validation 的规则以及您自己的规则。

用法

文档中的示例将假设此库已通过自动加载可用,并且已导入类 Respect\Assertion\Assert

Assert 类可以使用 Validation 中的任何规则,其输入作为其第一个参数

// will throw an exception => 1 must be equals 5
Assert::equals(1, 5);

// will throw an exception => "string" must be of type integer
Assert::intType('string');

// will not throw an exception
Assert::odd(5);

默认情况下,它抛出实例为 ValidationException 的异常,这意味着您可以捕获 InvalidArgumentException(或 LogicException)。

自定义消息

Assert 抛出的异常与 Validation 抛出的异常相同。这允许您使用模板自定义错误消息。

// will throw an exception => I was expecting 5, but you gave be 1
Assert::equals(1, 5, 'I was expecting {{compareTo}}, but you gave be {{input}}');

自定义异常

除了抛出 Validation 异常之外,您还可以使用自己的异常

// will throw the defined DomainException
Assert::between(42, 1, 10, new DomainException('Something is not right'));

如果您想为您的应用程序抛出特定的异常,这将非常有用。这是来自 Malukenho 的一个很好的想法!

链式断言(that()

您可以使用 Assert::that($input) 来链式断言,这使得您可以对相同输入执行多个断言,而无需重复。

// will throw an exception => I expected a positive number
Assert::that(-1)
    ->intVal('The number {{input}} must be an integer')
    ->positive('The number must be positive')
    ->lessThan(4);

在上面的示例中,只要任何断言失败,它就会抛出异常。如果您想链式验证并同时检查所有验证,我们建议您使用 Validation 的 API。

您还可以为整个链自定义消息或异常。

// will throw an exception => The number must be valid
Assert::that(0, new DomainException('The number must be valid'))
        ->positive()
        ->greaterThan(5);

// will throw an exception => But it is not greater than 5, though
Assert::that(3, 'The number must be valid')
        ->positive()
        ->greaterThan(5, 'But it is not greater than 5, though');

请注意,对特定断言的定制将覆盖整个链上的定制。

您还可以将以下前缀列表中前缀的效果应用于整个链。

// will throw an exception => 3 (the length of the input) must equal 4
Assert::that(['names' => ['Respect', 'Assertion'], 'options' => [1, 2, 3]])
    ->all()->arrayType()
    ->key('names')->allStringType()
    ->key('options')->lengthEquals(4);

还有一些特殊方法,允许您创建断言链。

  • thatAll():断言输入中的所有元素,并使用后续断言。
  • thatNot():反转后续断言,断言输入。
  • thatNullOr():如果输入不是null,则使用后续断言断言输入。
  • thatKey():使用后续断言断言输入中的一个键。
  • thatProperty():使用后续断言断言输入中的一个属性。

前缀

使用断言,您可以使用任何验证规则,但它还允许您使用前缀,以简化某些操作。

all*():断言输入中的所有元素

可以使用具有前缀all的断言来执行断言,这将断言输入中的所有元素,并使用具有前缀的断言。

// will throw an exception => "3" (like all items of the input) must be of type integer
Assert::allIntType([1, 2, '3']);

在某些情况下,您可能需要对输入中的所有元素执行多个断言。您可以使用thatAll()断言链,这将断言输入中的所有元素,并使用后续断言。

// will throw an exception => 3 (like all items of the input) must be between 1 and 2
Assert::thatAll([1, 2, 2, 1, 3])
    ->intVal()
    ->between(1, 2);

如果您想对所有元素执行多个断言,但还想对输入执行其他断言,则可以使用that()->all()

// will throw an exception => 5 (the length of the input) must be less than 4
Assert::that([1, 2, 2, 1, 3])
    ->arrayType()
    ->notEmpty()
    ->lengthGreaterThan(3)
    ->all()->intVal()->between(1, 2);

nullOr*():断言输入的值或null

可以使用具有前缀nullOr的断言来执行断言,只有当输入的值不为null时才会执行断言。

// will throw an exception => 42 must be negative
Assert::nullOrNegative(42);

// will not throw an exception
Assert::nullOrNegative(null);

// will throw an exception => 5 must be between 1 and 4
Assert::nullOrBetween(5, 1, 4);

// will not throw an exception
Assert::nullOrBetween(null, 1, 4);

在某些情况下,您可能需要对非null的值执行多个断言。在这种情况下,您可以使用thatNullOr()

// will throw an exception => 6 must be a valid prime number
Assert::thatNullOr(6)
        ->positive()
        ->between(1, 10)
        ->primeNumber();

// will not throw an exception
Assert::thatNullOr(null)
        ->positive()
        ->between(1, 10)
        ->primeNumber();

为了方便,您还可以使用that()->nullOr()

Assert::that(6)
    ->nullOr()->positive()->between(1, 10)->primeNumber();

not*():反转断言

您可以使用具有前缀not的断言来执行断言,这将断言具有前缀断言的相反面。

// will throw an exception => 2 must not be an even number
Assert::notEven(2);

// will throw an exception => 3 must not be in `{ 1, 2, 3, 4 }`
Assert::notIn(3, [1, 2, 3, 4]);

如果您需要反转多个规则,则可能更容易使用thatNot()that()->not()

// will throw an exception => "1" must not be positive
Assert::thatNot('1')
        ->intType()
        ->positive()
        ->between(1, 3);


// will throw an exception => "1" must not be positive
Assert::that('1')
        ->not()->intType()->positive()->between(1, 3);

key*():断言数组中的键

您可以使用keyPresent来检查键是否存在于数组中。

// will throw an exception => bar must be present
Assert::keyPresent(['foo' => true], 'bar');

您可以使用keyNotPresent来检查键是否存在于数组中。

// will throw an exception => bar must not be present
Assert::keyNotPresent(['bar' => 2], 'bar');

此外,使用key前缀,它将断言包含指定键的数组的值。

// will throw an exception => foo must equal 3
Assert::keyEquals(['foo' => 2], 'foo', 3);

// will throw an exception => bar must be negative
Assert::keyNegative(['bar' => 2], 'bar');

// will throw an exception => bar must not be of type integer
Assert::keyNotIntType(['bar' => 2], 'bar');

// will throw an exception => baz must be present
Assert::keyNegative(['foo' => 2], 'baz');

// will throw an exception => foo must exist
Assert::keyExists(['foo' => '/path/to/file.txt'], 'foo');

注意,keyExists断言将断言文件系统中是否存在键值foo

如果您想对输入的键执行多个断言,则可以使用thatKey()

// will throw an exception => 9 (the length of the input) must be less than 4
Assert::thatKey(['foo' => 'my-string'], 'foo')
        ->stringType()
        ->startsWith('my-')
        ->lengthLessThan(4);

如果您想对同一输入执行多个键断言,则可以使用that()->key()

// will throw an exception => bar must be less than 40
Assert::that(['foo' => 'my-string', 'bar' => 42])
        ->arrayType()
        ->key('foo')->stringType()->startsWith('my-')
        ->key('bar')->intType()->positive()->lessThan(40);

property*():断言对象中的属性

以下示例中将使用以下对象作为输入。

$input = new stdClass();
$input->foo = 1;

您可以使用propertyPresent来检查属性是否存在于对象中。

// will throw an exception => Attribute bar must be present
Assert::propertyPresent($input, 'bar');

您可以使用propertyNotPresent来检查属性是否不在对象中。

// will throw an exception => Attribute foo must not be present
Assert::propertyNotPresent($input, 'foo');

使用property前缀,您可以使用特定对象的属性的值进行断言。

// will throw an exception => foo must equal 3
Assert::propertyEquals($input, 'foo', 3);

// will throw an exception => foo must be negative
Assert::propertyNegative($input, 'foo');

// will throw an exception => foo must not be of type integer
Assert::propertyNotIntType($input, 'foo');

// will throw an exception => Attribute baz must be present
Assert::propertyNegative($input, 'baz');

// will throw an exception => foo must exists
Assert::propertyExists($input, 'foo');

注意,propertyExists断言将断言文件系统中是否存在属性值foo

如果您想对对象的属性执行多个断言,则可以使用thatProperty()

// will throw an exception => foo must be greater than 5
Assert::thatProperty($input, 'foo')
        ->intType()
        ->positive()
        ->greaterThan(5);

如果您想对同一输入执行多个键断言,则可以使用that()->property()

// will throw an exception => foo must be greater than 5
Assert::that($input)
        ->instance(stdClass::class)
        ->property('foo')->intType()->positive()->greaterThan(5);

length*():断言输入的长度

可以使用具有前缀length的断言来执行断言,这将断言输入的长度与具有前缀的断言。

// will throw an exception => 6 (the length of the input) must be between 10 and 15
Assert::lengthBetween('string', 10, 15);

length前缀也可以与数组和Countable实例一起使用。

// will throw an exception => 4 (the length of the input) must be an odd number
Assert::lengthOdd([1, 2, 3, 4]);

// will throw an exception => 3 (the length of the input) must be an even number
Assert::lengthEven(new ArrayObject([1, 2, 3]));

此库还允许您在length前缀之后使用not前缀。

// will throw an exception => 2 (the length of the input) must not be multiple of 2
Assert::lengthNotMultiple([1, 2], 2);

max*():断言输入的最大值

断言可以使用带前缀的 max 来执行,这将使用前缀断言输入的最大值

// will throw an exception => 3 (the maximum of the input) must be between 5 and 10
Assert::maxBetween([1, 2, 3], 5, 10);

max 前缀可以与任何 可迭代 值一起使用

// will throw an exception => 3 (the maximum of the input) must be an even number
Assert::maxEven([1, 2, 3]);

// will throw an exception => 60 (the maximum of the input) must be a valid perfect square
Assert::maxPerfectSquare(new ArrayObject([45, 60, 20]));

此库还允许您在 max 前缀之后使用 not 前缀

// will throw an exception => 23 (the maximum of the input) must not be positive
Assert::maxNotPositive([23, 7, 20]);

min*():断言输入的最小值

断言可以使用带前缀的 min 来执行,这将使用前缀断言输入的最小值

// will throw an exception => 1 (the minimum of the input) must be between 5 and 10
Assert::minBetween([1, 2, 3], 5, 10);

min 前缀可以与任何 可迭代 值一起使用

// will throw an exception => 1 (the minimum of the input) must be an even number
Assert::minEven([1, 2, 3]);

// will throw an exception => 20 (the minimum of the input) must be a valid perfect square
Assert::minPerfectSquare(new ArrayObject([45, 60, 20]));

此库还允许您在 min 前缀之后使用 not 前缀

// will throw an exception => 7 (the minimum of the input) must not be positive
Assert::minNotPositive([23, 7, 20]);