مكتبة 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 Storage:
<?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*
) للتحقق مما إذا كانت القيمة فارغة أو تحمل التأكيد:
<?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
يعد استخدام واجهة برمجة التطبيقات الثابتة على القيم أمرًا مطولًا للغاية عند التحقق من القيم مقابل تأكيدات متعددة. بدءًا من الإصدار 2.6.7 من Assert، توفر فئة Assert
واجهة برمجة تطبيقات أفضل بكثير للتأكيدات، بدءًا من 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 Assert::that()
بطلاقة، ولكن بدلاً من طرح استثناء مباشرةً، يقومون بجمع كافة الأخطاء وتشغيل الاستثناء فقط عندما يتم استدعاء الأسلوب verifyNow()
على كائن AssertSoftAssertion
.
<?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.
يمكنك أيضًا استرداد جميع AssertionFailedException
عن طريق استدعاء getErrorExceptions()
. يمكن أن يكون هذا مفيدًا على سبيل المثال لبناء استجابة الفشل للمستخدم.
بالنسبة لأولئك الذين يتطلعون إلى التقاط أخطاء متعددة في قيمة واحدة عند استخدام سلسلة تأكيد كسولة، يمكنك متابعة استدعاءك that
باستخدام tryAll
لتشغيل جميع التأكيدات مقابل القيمة، والتقاط جميع رسائل خطأ التأكيد الفاشلة الناتجة. هنا مثال:
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
الذي يشير إلى التأكيد الذي فشل.
يجب أن يقوم رد الاتصال بإرجاع السلسلة التي سيتم استخدامها كرسالة استثناء.
لحماية مكتبتك من الأخطاء المحتملة أو التفسيرات الخاطئة أو فواصل BC داخل التأكيد، يجب عليك تقديم فئة فرعية للتأكيد قائمة على المكتبة/المشروع، حيث يمكنك تجاوز الاستثناء الذي تم طرحه أيضًا.
بالإضافة إلى ذلك، يمكنك تجاوز طريقة AssertAssertion::stringify()
لتوفير تفسيراتك الخاصة للأنواع أثناء معالجة الأخطاء.
<?php
namespace MyProject ;
use Assert Assertion as BaseAssertion ;
class Assertion extends BaseAssertion
{
protected static $ exceptionClass = ' MyProjectAssertionFailedException ' ;
}
اعتبارًا من الإصدار 2.9.2، تتمتع التأكيدات الكسولة الآن بإمكانية الوصول إلى أي تأكيدات إضافية موجودة في فئات التأكيد الخاصة بك.
يرجى الاطلاع على المساهمة لمزيد من التفاصيل.