此包已废弃,不再维护。作者建议使用traderinteractive/filter包。

用于验证正确数据并执行典型数据修改的过滤实现

v4.2.0 2024-09-04 16:10 UTC

README

用于验证正确数据并执行典型数据修改的过滤实现。

Build Status Scrutinizer Code Quality Coverage Status

Latest Stable Version Latest Unstable Version License

Total Downloads Daily Downloads Monthly Downloads

特性

  • 紧凑、易读的规范
  • 支持使用任何PHP可调用函数进行过滤,例如
  • 匿名函数
  • 类函数
  • 内置函数
  • 可选/必需支持,字段和全局级别
  • 默认支持
  • 链式过滤
  • 可选返回未知字段
  • 过滤别名支持

组件

此包是一个部分元包,聚合以下组件

示例

class AppendFilter
{
    public function filter($value, $extraArg)
    {
        return $value . $extraArg;
    }
}
$appendFilter = new AppendFilter();

$trimFunc = function($val) { return trim($val); };

list($status, $result, $error, $unknowns) = TraderInteractive\Filterer::filter(
    [
        'field one' => [[$trimFunc], ['substr', 0, 3], [[$appendFilter, 'filter'], 'boo']],
        'field two' => ['required' => true, ['floatval']],
        'field three' => ['required' => false, ['float']],
        'field four' => ['required' => true, 'default' => 1, ['uint']],
    ],
    ['field one' => ' abcd', 'field two' => '3.14']
);

var_dump($status);
var_dump($result);
var_dump($error);
var_dump($unknowns);

打印

bool(true)
array(3) {
  'field one' =>
  string(6) "abcboo"
  'field two' =>
  double(3.14)
  'field four' =>
  int(1)
}
NULL
array(0) {
}

Composer

要作为本地、项目级依赖项添加库,请使用Composer!只需将traderinteractive/filter依赖项添加到您的项目的composer.json文件中,如下所示

composer require traderinteractive/filter

文档

源代码中找到,请查看!

Filterer

此库的核心是一个Filterer类,它可以验证数组的结构并通过过滤器映射数据。此行为由要应用的不同过滤器的规范和一些附加选项定义。

规范

规范是一个键 => 过滤器规范对的数组。

键定义了数组中的已知字段。数组中不在规范中的任何字段都被视为“未知”字段,并且可能因allowUnknowns选项的值而导致验证失败。

单个字段的过滤器规范也是一个数组。它可以包含预定义的过滤器选项

字段的其他规范是应用到此字段的过滤器。

过滤器中的第一个元素是要运行的过滤器。这可以是传递is_callable的任何内容(例如,'trim'[$object, 'method']),或者它可以是我们的预定义别名之一(例如,'float')。

过滤器中的其余元素是过滤器的额外参数(被过滤的值始终是第一个参数)。

过滤器规范可以包含任何数量的过滤器,每个过滤器的结果作为输入传递到下一个过滤器。最后一个过滤器的结果设置为结果数组。

上面的示例应该有助于阐明所有这些。

Filterer 选项

allowUnknowns

摘要

允许在未经过滤的输入中存在不在过滤器规范中的元素。

类型

  • bool

默认值

默认值是false

常量

TraderInteractive\FiltererOptions::ALLOW_UNKNOWNS

示例

$options = [
    TraderInteractive\FiltererOptions::ALLOW_UNKNOWNS => true,
];

$filterer = new TraderInteractive\Filterer($specification, $options);

defaultRequired

摘要

标志,用于定义过滤器规范中所有元素默认必需的行为。如果为true,则规范中的所有元素都是必需的,除非它们已设置必需的过滤器选项。

类型

  • bool

默认值

默认值是false

常量

TraderInteractive\FiltererOptions::DEFAULT_REQUIRED

示例

$options = [
    TraderInteractive\FiltererOptions::DEFAULT_REQUIRED => true,
];

$filterer = new TraderInteractive\Filterer($specification, $options);

responseType

摘要

指定了 Filterer::filter 方法返回的响应类型。可以是 数组\TraderInteractive\FilterResponse

类型

  • 字符串

默认值

默认值是 数组

常量

TraderInteractive\FiltererOptions::RESPONSE_TYPE

示例

$options = [
    TraderInteractive\FiltererOptions::RESPONSE_TYPE => \TraderInteractive\FilterResponse::class,
];

$filterer = new TraderInteractive\Filterer($specification, $options);

过滤器选项

必需

摘要

定义该字段是否为数组的必需元素。此值将覆盖全局过滤器指定的 defaultRequired 选项。

类型

  • bool

默认值

默认值取决于 defaultRequired 过滤器选项。

常量

TraderInteractive\FilterOptions::IS_REQUIRED

示例

$specificaton = [
    'id' => [TraderInteractive\FilterOptions::IS_REQUIRED => true, ['uint']],
];

默认

摘要

定义如果没有提供默认值,该字段的默认值是什么。具有默认值的字段将确保包含在结果中。required 值不影响 default 行为。

类型

  • 字符串

默认值

此选项没有默认值。

常量

TraderInteractive\FilterOptions::DEFAULT_VALUE

示例

$specificaton = [
    'subscribe' => [TraderInteractive\FilterOptions::DEFAULT_VALUE => true, ['bool']],
    'status' => [TraderInteractive\FilterOptions::DEFAULT_VALUE => 'A', ['string', false, 1, 1]],
];

错误

摘要

定义如果值过滤失败,将返回的自定义错误消息。在错误字符串中,可以使用 {value} 作为过滤失败的值的占位符。

类型

  • 字符串

默认值

此选项没有默认值。

常量

TraderInteractive\FilterOptions::CUSTOM_ERROR

示例

$specificaton = [
    'price' => [
        TraderInteractive\FilterOptions::CUSTOM_ERROR => 'Price {value} was not between 0 and 100', 
        ['uint', false, 0, 100],
    ],
];

conflictsWith

摘要

定义与给定字段冲突的任何输入字段。当输入一个字段或另一个字段但不两者同时输入时使用。

类型

  • 字符串

默认值

此选项没有默认值。

常量

TraderInteractive\FilterOptions::CONFLICTS_WITH

示例

$specification = [
    'id' => [
        TraderInteractive\FilterOptions::CONFLICTS_WITH => 'code',
        [['uint']],
    ],
    'code' => [
        TraderInteractive\FilterOptions::CONFLICTS_WITH => 'id',
        [['string']],
    ],
];

uses

摘要

指定应用作字段过滤器规范一部分的输入值数组。

类型

  • 字符串[]

默认值

此选项的默认值是一个空数组。

常量

TraderInteractive\FilterOptions::USES

示例

$specification = [
    'base' => [
        [['float']],
    ],
    'exponent' => [
        ['uint'], 
        [
            TraderInteractive\FilterOptions::USES => 'base',
            'pow',
        ],
    ],
];

指数过滤器规范将使用提供的值调用 PHP 函数 pow() 和过滤后的 base 的结果。

throwOnError

摘要

如果为真,Filterer 将在过滤值时抛出任何捕获到的异常,而不是在过滤器响应中返回错误。

类型

  • 布尔值

默认值

此选项的默认值是 false

常量

TraderInteractive\FilterOptions::THROW_ON_ERROR

示例

$idFilter = function ($id) : int {
    if (!is_int($id)) {
       throw new NotFoundException("id '{$id}' was not found"); 
    }
    
    return $id;
};
$specification = [
    'id' => [
        \TraderInteractive\FilterOptions::THROW_ON_ERROR => true,
        [$idFilter],
    ],
];

如果输入中给出的 id 值不是整数,Filterer::execute() 将抛出 NotFoundException

returnOnNull

摘要

标志,如果结果值为 null 则中断过滤器链。对于非空字段非常有用,如果值不为空,则需要额外的过滤。

类型

  • 布尔值

默认值

此选项的默认值是 false

常量

TraderInteractive\FilterOptions::RETURN_ON_NULL

示例

$validCodes = ['A', 'I', 'X'];
$specification = [
    'code' => [
        \TraderInteractive\FilterOptions::RETURN_ON_NULL => true,
        ['string', true],
        ['strtoupper'],
        ['in', $validCodes],
    ],
];

如果 code 值为 null,则过滤后的结果值将为 null。否则,值必须是 $validCode 之一。

包含的过滤器

当然,任何函数都可能有潜力用作过滤器,但我们包括一些有用的过滤器,并带有别名以处理常见情况。

Filterer::ofScalars

在过滤器器中以 ofScalars 别名,此过滤器验证参数是否为数组(可能是空的),其中每个元素都通过给定的过滤器(以与 Filterer::filter 相同的格式给出)。

以下检查 $value 是否为无符号整数的数组。

$value = \TraderInteractive\Filter\Filterer::ofScalars($value, [['uint']]);

Filterer::ofArrays

在过滤器器中以 ofArrays 别名,此过滤器验证参数是否为数组(可能是空的),其中每个元素都是数组,并通过给定的过滤器(以与 Filterer::filter 相同的格式给出)。

以下检查 $value 是否为具有 id 键的项的数组,其值为数字。不允许其他键。例如,以下输入是有效的:[['id' => '1'], ['id' => '2']]

$value = \TraderInteractive\Filter\Filterer::ofArrays($value, ['id' => [['uint']]]);

Filterer::ofArray

在过滤器器中以 ofArray 别名,此过滤器验证参数是否为数组,并符合给定的规范。这是 Filterer::filter 的反转版本,允许测试嵌套关联数组。

Arrays::copy

在过滤器器中以 array-copy 别名,此过滤器使用提供的目标键映射将源数组中的值复制到目标数组。

示例用法

$specification = ['field' => [['array-copy', ['FOO_VALUE' => 'foo', 'BAR_VALUE' => 'bar']]]];
$filterer = new TraderInteractive\Filterer($specification);
$input = ['foo' => 123, 'bar' => 'abc'];
$result = $filterer->execute($input);
assert(['field' => ['FOO_VALUE' => 123, 'BAR_VALUE' => 'abc']], $result->filteredValue);

Arrays::copyEach

在过滤器器中以 array-copy-each 别名,此过滤器使用提供的目标键映射将源数组中的每个数组的值复制到目标数组。

示例用法

$specification = ['field' => [['array-copy-each', ['FOO_VALUE' => 'foo', 'BAR_VALUE' => 'bar']]]];
$filterer = new TraderInteractive\Filterer($specification);
$input = [
    ['foo' => 123, 'bar' => 'abc'],
    ['foo' => 456, 'bar' => 'def'],
];
$result = $filterer->execute($input);
assert(['field' => [['FOO_VALUE' => 123, 'BAR_VALUE' => 'abc'], ['FOO_VALUE' => 456, 'BAR_VALUE' => 'def']]], $result->filteredValue);

Arrays::implode

在过滤器器中以 implode 别名,此过滤器是 implode 的包装,以确保正确的参数顺序。

$sepcification = ['field' => [['array'],['implode', ',']]];
$filterer = new TraderInteractive\Filterer($specification);
$input = [
    'field' => ['lastname', 'email', 'phone'],
];
$result = $filterer->execute($input);
assert(['field' => 'lastname,email,phone'], $result->filteredValue);

Arrays::in

在过滤器中以 in 别名,此过滤器是 in_array 的包装,包括对严格相等性测试的支持。

以下对 $value 进行了严格检查,以与3个接受值进行对比。

\TraderInteractive\Filter\Arrays::in($value, ['a', 'b', 'c']);

Arrays::arrayize

在过滤器中以 arrayize 别名,此过滤器如果输入是数组,则返回原始输入,否则返回包裹在数组中的输入。如果原始输入为null,则返回空数组。

$value = \TraderInteractive\Filter\Arrays::arrayize('a string value');
assert($value === ['a string value']);

Arrays::filter

在过滤器中以 array 别名,此过滤器验证参数是否为数组,并检查数组的长度是否在范围内。默认范围是1+,所以空数组默认失败。

以下检查 $value 是否为一个恰好有3个元素的数组。

\TraderInteractive\Filter\Arrays::filter($value, 3, 3);

Arrays::flatten

在过滤器中以 flatten 别名,此过滤器将多维数组扁平化为单维数组。值顺序将保持不变,但键本身将不会。例如

$value = \TraderInteractive\Filter\Arrays::flatten([[1, 2], [3, [4, 5]]]);
assert($value === [1, 2, 3, 4, 5]);

Arrays::pad

在过滤器中以 array-pad 别名,此过滤器使用指定值填充数组到指定长度。可以选择性地向前或向后填充数组。

示例用法

$specification = ['field' => [['array-pad', 5, 0, Arrays::ARRAY_PAD_LEFT]]],
$filterer = new TraderInteractive\Filterer($specification);
$input = [2, 4, 6];
$result = $filterer->execute($input);
assert(['field' => [0, 0, 2, 4, 6]], $result->filteredValue);

Booleans::filter

在过滤器中以 bool 别名,此过滤器验证参数是否为布尔值或映射到布尔值的字符串。第二个参数可以设置为 true 以允许通过null值而不引发错误(它们将保持null并不会转换为false)。最后几个参数是字符串列表,分别表示true值和false值。默认情况下,字符串 "true" 和 "false" 映射到它们的布尔对应值。

以下示例将 $value 转换为布尔值,允许字符串 "on" 和 "of"。

$enabled = \TraderInteractive\Filter\Booleans::filter($value, false, ['on'], ['off']);

Booleans::convert

在过滤器中以 bool-convert 别名,此过滤器将给定的布尔值转换为提供的true或false条件。默认返回值是字符串 'true' 和 'false'

以下将布尔值 $value 转换为 'yes' 或 'no'

$answer = \TraderInteractive\Filter\Booleans::convert($value, 'yes', 'no');

Floats/Ints/UnsignedInt::filter

分别以 floatintuint 别名,这些过滤器验证参数是否为正确的数字类型,并允许进行范围检查。每个的第二个参数可以设置为 true 以允许通过null值而不引发错误(它们将保持null并不会转换为false)。接下来两个参数是最小和最大范围,可以用来限制允许数字的范围。

非数字字符串将验证失败,数字字符串将被转换。

浮点参数有一个额外的参数可以设置为 true 以将整数转换为浮点数。如果没有这个参数,整数将验证失败。

以下检查 $value 是否为一个介于1和100之间的整数(包括1和100),并返回该整数(如果它是一个字符串,则进行转换)。

$value = \TraderInteractive\Filter\UnsignedInt::filter($value, false, 1, 100);

Strings::filter

在过滤器中以 string 别名,此过滤器验证参数是否为字符串。第二个参数可以设置为 true 以允许通过null值而不引发错误(它们将保持null并不会转换为false)。最后几个参数指定字符串的长度范围。默认范围是1+,所以空字符串默认失败。

以下检查 $value 是否为一个非空字符串。

\TraderInteractive\Filter\Strings::filter($value);

Strings::concat

在过滤器中以 concat 别名,此过滤器连接给定的 $value、$prefix 和 $suffix 并返回结果字符串。

$value = \TraderInteractive\Filter\Strings::concat('middle', 'begining_', '_end');
assert($value === 'begining_middle_end');

Strings::explode

在过滤器中以 explode 别名,此过滤器实际上是内置 explode 方法的包装,将值放在顺序的第一位,以便与 Filterer 一起使用。它还默认使用 , 作为分隔符。例如

$value = \TraderInteractive\Filter\Strings::explode('abc,def,ghi');
assert($value === ['abc', 'def', 'ghi']);

Strings::stripTags

在过滤器中别名为strip-tags,此过滤器本质上是对内置的strip_tags函数的包装。然而,与原生函数不同,当stripTags方法接收到null值时,它将返回null。

$value = \TraderInteractive\Filter\Strings::stripTags('A string with <p>tags</p>');
assert($value === 'a string with tags');

Strings::translate

在过滤器中别名为translate,此过滤器接受一个字符串值,并返回其在给定的$valueMap中找到的翻译值。

$value = \TraderInteractive\Filter\Strings::tranlsate('bar', ['foo' => 'translated to bar', 'bar' => 'translated to foo']);
assert($value === 'translated to foo');

Url::filter

在过滤器中别名为url,此过滤器验证参数是否为符合RFC2396的URL字符串。第二个参数可以设置为true以允许null值通过而不会产生错误(它们将保持null状态,不会被转换为false)。

以下检查$value是否是一个URL。

\TraderInteractive\Filter\Url::filter($value);

Closures::filter

在过滤器中别名为closure,此过滤器验证参数是否是闭包函数。

以下检查$closureMethod是否是闭包。

$closureMethod = function () {
    doSomething();
};
\TraderInteractive\Filter\Closures::filter($closureMethod);

Email::filter

在过滤器中别名为email,此过滤器验证参数是否是电子邮件。

以下检查$value是否是电子邮件。

\TraderInteractive\Filter\Email::filter($value);

DateTime::filter

在过滤器中别名为date,这将值作为\DateTime对象进行过滤。值可以是任何符合PHP的有效日期/时间格式的字符串。

以下检查$value是否是日期/时间。

$dateTime = \TraderInteractive\Filter\DateTime::filter('2014-02-04T11:55:00-0500');

DateTime::format

在过滤器中别名为date-format,这将给定的`\DateTime`值根据给定的格式转换为字符串。

以下为给定的`\DateTime` $value返回格式化的字符串。

$formatted = \TraderInteractive\Filter\DateTime::format($value, 'Y-m-d H:i:s');

DateTimeZone::filter

在过滤器中别名为date,这将值作为\DateTimeZone对象进行过滤。值可以是任何受支持的时区名称

以下检查$value是否是时区。

$timezone = \TraderInteractive\Filter\DateTimeZone::filter('America/New_York');

Json::validate

在过滤器中别名为json,检查JSON是否有效并返回原始值。

以下确保$value是有效的JSON。

$value = \TraderInteractive\Filter\Json::validate('{"foo": "bar"}');

Json::parse

在过滤器中别名为json-decode,检查JSON是否有效并返回解码的结果。

以下解码给定的值并返回结果。

$value = \TraderInteractive\Filter\Json::parse('{"foo": "bar"}');
assert($value === ['foo' => 'bar']);

PhoneFilter::filter

在过滤器中别名为phone,这将给定的值作为电话进行过滤,以指定的格式返回电话。

以下将给定的字符串过滤为格式化的电话字符串。

$value = \TraderInteractive\Filter\PhoneFilter::filter('234.567.8901', false, '({area}) {exchange}-{station}');
assert($value === '(234) 567-8901');

TimeOfDayFilter::filter

在过滤器中别名为time-of-day,这将给定的字符串值过滤为HH:MM:SS格式的每天时间。

以下确保$value是有效的HH:MM:SS格式字符串。

$value = \TraderInteractive\Filter\TimeOfDayFilter::filter('12:15:23');
assert($value === '12:15:23');

XmlFilter::filter

在过滤器中别名为xml,这将确保给定的字符串值是有效的XML,并返回原始值。

以下确保给定的字符串是有效的XML。

$value = <<<XML
<?xml version="1.0"?>
<books>
    <book id="bk101">
        <author>Gambardella, Matthew</author>
        <title>XML Developers Guide</title>
        <genre>Computer</genre>
        <price>44.95</price>
        <publish_date>2000-10-01</publish_date>
        <description>An in-depth look at creating applications with XML.</description>
    </book>
    <book id="bk102">
        <author>Ralls, Kim</author>
        <title>Midnight Rain</title>
        <genre>Fantasy</genre>
        <price>5.95</price>
        <publish_date>2000-12-16</publish_date>
        <description>A former architect battles corporate zombies</description>
    </book>
</books>
XML;
$xml = \TraderInteractive\Filter\XmlFilter::filter($value);

XmlFilter::extract

在过滤器中别名为xml-extract,这将确保给定的字符串值是有效的XML,然后提取并返回给定xpath中找到的元素。

以下确保给定的字符串是有效的XML,并返回第一本书的标题元素。

$value = <<<XML
<?xml version="1.0"?>
<books>
    <book id="bk101">
        <author>Gambardella, Matthew</author>
        <title>XML Developers Guide</title>
        <genre>Computer</genre>
        <price>44.95</price>
        <publish_date>2000-10-01</publish_date>
        <description>An in-depth look at creating applications with XML.</description>
    </book>
    <book id="bk102">
        <author>Ralls, Kim</author>
        <title>Midnight Rain</title>
        <genre>Fantasy</genre>
        <price>5.95</price>
        <publish_date>2000-12-16</publish_date>
        <description>A former architect battles corporate zombies</description>
    </book>
</books>
XML;
$xpath = "/books/book[@id='bk101']/title";
$titleXml = \TraderInteractive\Filter\XmlFilter::extract($value, $xpath);
assert($titleXml === '<title>XML Developers Guide</title>');

XmlFilter::validate

在过滤器中别名为xml-validate,这将确保给定的字符串值是有效的XML,并确认符合给定的XSD文件。原始值将被返回。

以下确保给定的字符串是有效的XML,并匹配books.xsd。

$value = <<<XML
<?xml version="1.0"?>
<books>
    <book id="bk101">
        <author>Gambardella, Matthew</author>
        <title>XML Developers Guide</title>
        <genre>Computer</genre>
        <price>44.95</price>
        <publish_date>2000-10-01</publish_date>
        <description>An in-depth look at creating applications with XML.</description>
    </book>
    <book id="bk102">
        <author>Ralls, Kim</author>
        <title>Midnight Rain</title>
        <genre>Fantasy</genre>
        <price>5.95</price>
        <publish_date>2000-12-16</publish_date>
        <description>A former architect battles corporate zombies</description>
    </book>
</books>
XML;
$xml = \TraderInteractive\Filter\XmlFilter::validate($value, 'books.xsd');

Contact

开发者可以通过以下方式联系:

项目构建

使用代码检出,在您的PATH中获取Composer并运行

./build.php

此外,还有一个基于dockerfig配置,可以在docker容器内执行构建。这是一种构建应用程序的简单方法

fig run build

有关我们构建过程的更多信息,请参阅我们的贡献指南