respect / 断言
将 Respect\Validation 的强大功能融入断言库
Requires
- php: ^8.1
- respect/stringifier: ^0.2.0
- respect/validation: ^2.2.4
- symfony/polyfill-mbstring: ^v1.27.0
Requires (Dev)
- malukenho/docheader: ^0.1.8
- phpstan/phpstan: ^1.10.7
- phpstan/phpstan-deprecation-rules: ^1.1.3
- phpstan/phpstan-phpunit: ^1.3.10
- phpunit/phpunit: ^10.0.17
- respect/coding-standard: ^4.0.0
- squizlabs/php_codesniffer: ^3.7.2
Suggests
- ext-mbstring: Multibyte String Functions
README
将 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]);