acgrid/assert

此包已被废弃,不再维护。作者建议使用 beberlei/assert 包。

适用于业务模型输入验证的轻量级断言库。

维护者

详细信息

github.com/acgrid/assert

源代码

v2.6.5.1 2016-10-18 08:51 UTC

README

Travis 状态: Build Status

这是一个个人分叉版本。它已被重写,以便所有组件都可以在用户层被覆盖。 此外,由于类名常量,此分叉仅在 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