acgrid / assert
Requires
- php: >=5.5
- ext-mbstring: *
Requires (Dev)
- friendsofphp/php-cs-fixer: 2.0.0-alpha
- phpunit/phpunit: @stable
README
这是一个个人分叉版本。它已被重写,以便所有组件都可以在用户层被覆盖。 此外,由于类名常量,此分叉仅在 PHP 5.5 或更高版本上才能工作。
一个简单的 PHP 库,包含断言和守卫方法,用于在业务模型、库和应用底层代码中进行输入验证(不是过滤!)该库可用于对输入数据实现前置/后置条件。
想法是减少在模型中实现断言的代码量,并简化实现断言的代码路径。当断言失败时,会抛出异常,从而消除了在代码中使用 if-语句的必要性。
出于以下原因,库未使用 Symfony 或 Zend 验证器:检查必须是低级、快速、非面向对象的代码,以便在所有必要的地方使用。使用这两个库中的任何一个都需要实例化多个对象,使用区域组件、翻译等。这太过冗余。
安装
使用 Composer
composer require acgrid/assert
示例用法
<?php use acgrid\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 use acgrid\Assert\Assertion; class Foo{ 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); } }
NullOr 辅助函数
提供辅助方法(Assertion::nullOr*
)来检查值是否为 null 或满足断言
<?php use acgrid\Assert\Assertion; Assertion::nullOrMax(null, 42); // success Assertion::nullOrMax(1, 42); // success Assertion::nullOrMax(1337, 42); // exception
All 辅助函数
Assertion::all*
方法检查所有提供的值是否满足断言。如果断言不适用于其中一个值,它将抛出异常
<?php use acgrid\Assert\Assertion; Assertion::allIsInstanceOf(array(new \stdClass, new \stdClass), 'stdClass'); // success Assertion::allIsInstanceOf(array(new \stdClass, new \stdClass), 'PDO'); // exception
\acgrid\Assert\that() 连接
当检查多个断言时,使用值上的静态 API 检查值会非常冗长。从 Assert 2.0 开始,断言有一个更简洁的流畅 API,从 \acgrid\Assert\that($value)
开始,然后接收要调用在流畅接口上的断言。您只需要指定一次 $value
。
<?php \acgrid\Assert\that($value)->notEmpty()->integer(); \acgrid\Assert\that($value)->nullOr()->string()->startsWith("Foo"); \acgrid\Assert\that($values)->all()->float();
还有两个快捷函数 \acgrid\Assert\thatNullOr()
和 \acgrid\Assert\thatAll()
,分别启用 "nullOr" 或 "all" 辅助函数。
懒断言
在 Web 开发中,尤其是在涉及表单的情况下,您可能希望收集多个错误而不是直接在第一个错误时中止。这就是懒断言的作用。它们的 API 与流畅的 \acgrid\Assert\that()
API 完全一样,但它们不会直接抛出异常,而是收集所有错误,并在调用 acgrid\Assert\SoftAssertion
对象上的 verifyNow()
方法时触发异常。
<?php \acgrid\Assert\lazy() ->that(10, 'foo')->string() ->that(null, 'bar')->notEmpty() ->that('string', 'baz')->isArray() ->verifyNow();
方法 that($value, $propertyPath)
需要属性路径(名称),这样您就可以在之后区分错误。
在失败时,verifyNow()
将抛出一个包含合并消息的异常 acgrid\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
。例如,这可以用于构建用户的失败响应。
断言列表
<?php use acgrid\Assert\Assertion; Assertion::alnum($value); Assertion::between($value, $lowerLimit, $upperLimit); Assertion::betweenExclusive($value, $lowerLimit, $upperLimit); Assertion::betweenLength($value, $minLength, $maxLength); Assertion::boolean($value); Assertion::choice($value, $choices); Assertion::choicesNotEmpty($values, $choices); Assertion::classExists($value); Assertion::contains($string, $needle); Assertion::count($countable, $count); Assertion::date($value, $format); Assertion::digit($value); Assertion::directory($value); Assertion::e164($value); Assertion::email($value); Assertion::endsWith($string, $needle); Assertion::eq($value, $value2); Assertion::false($value); Assertion::file($value); Assertion::float($value); Assertion::greaterOrEqualThan($value, $limit); Assertion::greaterThan($value, $limit); Assertion::implementsInterface($class, $interfaceName); Assertion::inArray($value, $choices); Assertion::integer($value); Assertion::integerish($value); Assertion::interfaceExists($value); Assertion::ip($value, $flag = null); Assertion::ipv4($value, $flag = null); Assertion::ipv6($value, $flag = null); Assertion::isArray($value); Assertion::isArrayAccessible($value); Assertion::isCallable($value); Assertion::isInstanceOf($value, $className); Assertion::isJsonString($value); Assertion::isObject($value); Assertion::isTraversable($value); Assertion::keyExists($value, $key); Assertion::keyIsset($value, $key); Assertion::keyNotExists($value, $key); Assertion::length($value, $length); Assertion::lessOrEqualThan($value, $limit); Assertion::lessThan($value, $limit); Assertion::max($value, $maxValue); Assertion::maxLength($value, $maxLength); Assertion::methodExists($value, $object); Assertion::min($value, $minValue); Assertion::minLength($value, $minLength); Assertion::noContent($value); Assertion::notBlank($value); Assertion::notEmpty($value); Assertion::notEmptyKey($value, $key); Assertion::notEq($value1, $value2); Assertion::notInArray($value, $choices); Assertion::notIsInstanceOf($value, $className); Assertion::notNull($value); Assertion::notSame($value1, $value2); Assertion::null($value); Assertion::numeric($value); Assertion::range($value, $minValue, $maxValue); Assertion::readable($value); Assertion::regex($value, $pattern); Assertion::same($value, $value2); Assertion::satisfy($value, $callback); Assertion::scalar($value); Assertion::startsWith($string, $needle); Assertion::string($value); Assertion::subclassOf($value, $className); Assertion::true($value); Assertion::url($value); Assertion::uuid($value); Assertion::writeable($value);
记住:当配置参数是必要的,它总是传递在值之后。值总是第一个参数。
异常 & 错误处理
如果任何一个断言失败,则会抛出 acgrid\Assert\AssertionFailedException
。您可以将一个名为 $message
的参数传递给任何一个断言来控制异常消息。每个异常默认都包含一个默认消息和唯一的消息代码。
<?php use acgrid\Assert\Assertion; use acgrid\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. }
acgrid\Assert\AssertionFailedException
只是一个接口,默认实现是 acgrid\Assert\InvalidArgumentException
,它扩展了 SPL 的 InvalidArgumentException
。您可以在包级别更改所使用的异常。
您的断言类
为了保护您的库免受 Assert 内部可能的错误、误解或 BC 破坏的影响,您应该引入一个基于库/项目的断言子类,在那里您可以覆盖抛出的异常。此外,您还可以覆盖 acgrid\Assert\Assertion::stringify()
方法来提供您在错误处理期间对类型的自定义解释。
<?php namespace MyProject; use acgrid\Assert\Assertion as BaseAssertion; use acgrid\Assert\LazyAssertion; class Assertion extends BaseAssertion { protected static $exceptionClass = 'MyProject\AssertionFailedException'; } class MyLazyAssertion extends LazyAssertion { protected static $exceptionClass = 'MyProject\LazyAssertionFailedException'; }
您还可以配置将调用哪个静态类进行函数辅助程序
<?php // something like bootstrap.php, set the class to be used: \acgrid\Assert\chainClass(Assert\Tests\MyChain::class); \acgrid\Assert\lazyClass(Assert\Tests\MyLazyAssertion::class); // as getter: var_dump(\acgrid\Assert\chainClass()); var_dump(\acgrid\Assert\lazyClass());
贡献
有关更多详细信息,请参阅 CONTRIBUTING。