一个简单的 php 库,其中包含用于业务模型、库和应用程序低级代码中输入验证(而不是过滤!)的断言和保护方法。该库可用于对输入数据实施前置/后置条件。
想法是减少模型中实现断言的代码量,并简化实现断言的代码路径。当断言失败时,会引发异常,从而消除代码中使用 if 子句的必要性。
该库不使用 Symfony 或 Zend Validators 是有原因的:检查必须是低级、快速、非面向对象的代码,以便在任何需要的地方使用。使用这两个库中的任何一个都需要实例化多个对象,使用区域设置组件、翻译等等。它太臃肿了。
使用作曲家:
composer require beberlei/assert
<?php
use Assert Assertion ;
function duplicateFile ( $ file , $ times )
{
Assertion :: file ( $ file );
Assertion :: digit ( $ times );
for ( $ i = 0 ; $ i < $ times ; $ i ++) {
copy ( $ file , $ file . $ i );
}
}
Azure Blob 存储的实时使用情况:
<?php
public function putBlob ( $ containerName = '' , $ blobName = '' , $ localFileName = '' , $ metadata = array (), $ leaseId = null , $ additionalHeaders = array ())
{
Assertion :: notEmpty ( $ containerName , ' Container name is not specified ' );
self :: assertValidContainerName ( $ containerName );
Assertion :: notEmpty ( $ blobName , ' Blob name is not specified. ' );
Assertion :: notEmpty ( $ localFileName , ' Local file name is not specified. ' );
Assertion :: file ( $ localFileName , ' Local file name is not specified. ' );
self :: assertValidRootContainerBlobName ( $ containerName , $ blobName );
// Check file size
if ( filesize ( $ localFileName ) >= self :: MAX_BLOB_SIZE ) {
return $ this -> putLargeBlob ( $ containerName , $ blobName , $ localFileName , $ metadata , $ leaseId , $ additionalHeaders );
}
// Put the data to Windows Azure Storage
return $ this -> putBlobData ( $ containerName , $ blobName , file_get_contents ( $ localFileName ), $ metadata , $ leaseId , $ additionalHeaders );
}
提供了一个辅助方法 ( Assertion::nullOr*
) 来检查断言是否为 null 或:
<?php
Assertion :: nullOrMax ( null , 42 ); // success
Assertion :: nullOrMax ( 1 , 42 ); // success
Assertion :: nullOrMax ( 1337 , 42 ); // exception
Assertion::all*
方法检查所有提供的值是否都适用于断言。它将抛出断言不适用于其中一个值的异常:
<?php
Assertion :: allIsInstanceOf ( array ( new stdClass, new stdClass), ' stdClass ' ); // success
Assertion :: allIsInstanceOf ( array ( new stdClass, new stdClass), ' PDO ' ); // exception
在根据多个断言检查值时,对值使用静态 API 非常冗长。从 Assert 2.6.7 开始, Assert
类为断言提供了一个更好的流畅 API,从Assert::that($value)
开始,然后接收您想要在流畅接口上调用的断言。您只需指定$value
一次。
<?php
Assert :: that ( $ value )-> notEmpty ()-> integer ();
Assert :: that ( $ value )-> nullOr ()-> string ()-> startsWith ( " Foo " );
Assert :: that ( $ values )-> all ()-> float ();
还有两个快捷函数Assert::thatNullOr()
和Assert::thatAll()
分别启用“nullOr”或“all”帮助器。
在Web开发中有很多情况,特别是在涉及表单时,您希望收集多个错误,而不是在出现第一个错误时直接中止。这就是惰性断言的用途。它们的 API 的工作方式与 Fluent Assert::that()
API 完全相同,但它们不是直接抛出异常,而是收集所有错误,并且仅在AssertSoftAssertion
对象上调用verifyNow()
方法时触发异常。
<?php
Assert :: lazy ()
-> that ( 10 , ' foo ' )-> string ()
-> that ( null , ' bar ' )-> notEmpty ()
-> that ( ' string ' , ' baz ' )-> isArray ()
-> verifyNow ();
that($value, $propertyPath)
方法需要一个属性路径(名称),以便您知道如何区分错误。
失败时verifyNow()
将抛出异常Assert\LazyAssertionException
并带有组合消息:
The following 3 assertions failed:
1) foo: Value "10" expected to be string, type integer given.
2) bar: Value "<NULL>" is empty, but non empty value was expected.
3) baz: Value "string" is not an array.
您还可以通过调用getErrorExceptions()
检索所有AssertionFailedException
。例如,这对于为用户构建失败响应非常有用。
对于那些希望在使用惰性断言链时捕获单个值上的多个错误的人,您可以使用tryAll
来跟踪that
调用,以针对该值运行所有断言,并捕获所有由此产生的失败断言错误消息。这是一个例子:
Assert :: lazy ()
-> that ( 10 , ' foo ' )-> tryAll ()-> integer ()-> between ( 5 , 15 )
-> that ( null , ' foo ' )-> tryAll ()-> notEmpty ()-> string ()
-> verifyNow ();
上面展示了如何使用此功能来微调报告失败的行为,但为了更轻松地捕获所有失败,您还可以在进行任何断言之前调用tryAll
,如下所示。这有助于减少方法调用,并且具有与上面相同的行为。
Assert :: lazy ()-> tryAll ()
-> that ( 10 , ' foo ' )-> integer ()-> between ( 5 , 15 )
-> that ( null , ' foo ' )-> notEmpty ()-> string ()
-> verifyNow ();
以下函数作为Assert
静态构造函数的别名存在:
Assertthat()
AssertthatAll()
AssertthatNullOr()
Assertlazy()
使用函数式或静态构造函数完全是个人喜好。
注意:函数构造函数不能与Assertion
扩展一起使用。然而,以指向扩展类的方式重新创建这些函数是微不足道的。
<?php
use Assert Assertion ;
Assertion :: alnum (mixed $ value );
Assertion :: base64 (string $ value );
Assertion :: between (mixed $ value , mixed $ lowerLimit , mixed $ upperLimit );
Assertion :: betweenExclusive (mixed $ value , mixed $ lowerLimit , mixed $ upperLimit );
Assertion :: betweenLength (mixed $ value , int $ minLength , int $ maxLength );
Assertion :: boolean (mixed $ value );
Assertion :: choice (mixed $ value , array $ choices );
Assertion :: choicesNotEmpty (array $ values , array $ choices );
Assertion :: classExists (mixed $ value );
Assertion :: contains (mixed $ string , string $ needle );
Assertion ::count(array| Countable | ResourceBundle | SimpleXMLElement $ countable , int $ count );
Assertion :: date (string $ value , string $ format );
Assertion :: defined (mixed $ constant );
Assertion :: digit (mixed $ value );
Assertion :: directory (string $ value );
Assertion :: e164 (string $ value );
Assertion :: email (mixed $ value );
Assertion :: endsWith (mixed $ string , string $ needle );
Assertion :: eq (mixed $ value , mixed $ value2 );
Assertion :: eqArraySubset (mixed $ value , mixed $ value2 );
Assertion :: extensionLoaded (mixed $ value );
Assertion :: extensionVersion (string $ extension , string $ operator , mixed $ version );
Assertion :: false (mixed $ value );
Assertion :: file (string $ value );
Assertion :: float (mixed $ value );
Assertion :: greaterOrEqualThan (mixed $ value , mixed $ limit );
Assertion :: greaterThan (mixed $ value , mixed $ limit );
Assertion :: implementsInterface (mixed $ class , string $ interfaceName );
Assertion :: inArray (mixed $ value , array $ choices );
Assertion :: integer (mixed $ value );
Assertion :: integerish (mixed $ value );
Assertion :: interfaceExists (mixed $ value );
Assertion :: ip (string $ value , int $ flag = null );
Assertion :: ipv4 (string $ value , int $ flag = null );
Assertion :: ipv6 (string $ value , int $ flag = null );
Assertion :: isArray (mixed $ value );
Assertion :: isArrayAccessible (mixed $ value );
Assertion :: isCallable (mixed $ value );
Assertion ::isCountable(array| Countable | ResourceBundle | SimpleXMLElement $ value );
Assertion :: isInstanceOf (mixed $ value , string $ className );
Assertion :: isJsonString (mixed $ value );
Assertion :: isObject (mixed $ value );
Assertion :: isResource (mixed $ value );
Assertion :: isTraversable (mixed $ value );
Assertion :: keyExists (mixed $ value , string|int $ key );
Assertion :: keyIsset (mixed $ value , string|int $ key );
Assertion :: keyNotExists (mixed $ value , string|int $ key );
Assertion :: length (mixed $ value , int $ length );
Assertion :: lessOrEqualThan (mixed $ value , mixed $ limit );
Assertion :: lessThan (mixed $ value , mixed $ limit );
Assertion :: max (mixed $ value , mixed $ maxValue );
Assertion ::maxCount(array| Countable | ResourceBundle | SimpleXMLElement $ countable , int $ count );
Assertion :: maxLength (mixed $ value , int $ maxLength );
Assertion :: methodExists (string $ value , mixed $ object );
Assertion :: min (mixed $ value , mixed $ minValue );
Assertion ::minCount(array| Countable | ResourceBundle | SimpleXMLElement $ countable , int $ count );
Assertion :: minLength (mixed $ value , int $ minLength );
Assertion :: noContent (mixed $ value );
Assertion :: notBlank (mixed $ value );
Assertion :: notContains (mixed $ string , string $ needle );
Assertion :: notEmpty (mixed $ value );
Assertion :: notEmptyKey (mixed $ value , string|int $ key );
Assertion :: notEq (mixed $ value1 , mixed $ value2 );
Assertion :: notInArray (mixed $ value , array $ choices );
Assertion :: notIsInstanceOf (mixed $ value , string $ className );
Assertion :: notNull (mixed $ value );
Assertion :: notRegex (mixed $ value , string $ pattern );
Assertion :: notSame (mixed $ value1 , mixed $ value2 );
Assertion :: null (mixed $ value );
Assertion :: numeric (mixed $ value );
Assertion :: objectOrClass (mixed $ value );
Assertion :: phpVersion (string $ operator , mixed $ version );
Assertion :: propertiesExist (mixed $ value , array $ properties );
Assertion :: propertyExists (mixed $ value , string $ property );
Assertion :: range (mixed $ value , mixed $ minValue , mixed $ maxValue );
Assertion :: readable (string $ value );
Assertion :: regex (mixed $ value , string $ pattern );
Assertion :: same (mixed $ value , mixed $ value2 );
Assertion :: satisfy (mixed $ value , callable $ callback );
Assertion :: scalar (mixed $ value );
Assertion :: startsWith (mixed $ string , string $ needle );
Assertion :: string (mixed $ value );
Assertion :: subclassOf (mixed $ value , string $ className );
Assertion :: true (mixed $ value );
Assertion :: uniqueValues (array $ values );
Assertion :: url (mixed $ value );
Assertion :: uuid (string $ value );
Assertion :: version (string $ version1 , string $ operator , string $ version2 );
Assertion :: writeable (string $ value );
请记住:当需要配置参数时,它始终在值之后传递。该值始终是第一个参数。
如果任何断言失败,则会抛出AssertAssertionFailedException
。您可以将名为$message
参数传递给任何断言来控制异常消息。默认情况下,每个异常都包含一条默认消息和唯一的消息代码。
<?php
use Assert Assertion ;
use Assert AssertionFailedException ;
try {
Assertion :: integer ( $ value , " The pressure of gas is measured in integers. " );
} catch ( AssertionFailedException $ e ) {
// error handling
$ e -> getValue (); // the value that caused the failure
$ e -> getConstraints (); // the additional constraints of the assertion.
}
AssertAssertionFailedException
只是一个接口,默认实现是AssertInvalidArgumentException
,它扩展了 SPL InvalidArgumentException
。您可以更改在基于包的级别上使用的异常。
您可以传递回调作为消息参数,这样您就可以仅在断言失败时构造自己的消息,而不是每次运行测试时都构造消息。
回调将提供一个用于断言的参数数组。
由于某些断言调用其他断言,您的回调将需要对数组进行示例以确定哪个断言失败。
该数组将包含一个名为::assertion
的键,指示哪个断言失败。
回调应返回将用作异常消息的字符串。
为了保护您的库免受 Assert 中可能出现的错误、误解或 BC 中断的影响,您应该引入一个基于库/项目的断言子类,您也可以在其中覆盖抛出的异常。
此外,您可以重写AssertAssertion::stringify()
方法,以在错误处理期间提供您自己的类型解释。
<?php
namespace MyProject ;
use Assert Assertion as BaseAssertion ;
class Assertion extends BaseAssertion
{
protected static $ exceptionClass = ' MyProjectAssertionFailedException ' ;
}
从 V2.9.2 开始,惰性断言现在可以访问您自己的断言类中存在的任何其他断言。
请参阅贡献了解更多详细信息。