一個簡單的 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」幫助器。
在網路開發中有很多情況,特別是在涉及表單時,您希望收集多個錯誤,而不是在出現第一個錯誤時直接中止。這就是惰性斷言的用途。它們的 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 開始,惰性斷言現在可以存取您自己的斷言類別中存在的任何其他斷言。
請參閱貢獻以了解更多詳細資訊。