neunerlei/options

一个小助手,可以用于将模式应用于任何给定的数组

2.0.0 2022-02-21 18:22 UTC

This package is auto-updated.

Last update: 2024-09-22 00:07:48 UTC


README

这个小巧的助手可以用于将模式应用于任何给定的数组。它设计为方法选项的即时验证器,但也足够强大,可以验证各种API请求。

安装

使用composer安装此包

composer require neunerlei/options

基本用法

该包的主要目的是验证传递给方法或函数的选项,如下面基本示例所示

use Neunerlei\Options\Options;
function myFunc(array $options = []){
    // Apply the options
    $options = Options::make($options, [
        "foo" => 123,
        "bar" => null,
    ]);
    print_r($options);
}

myFunc(); // Prints: ["foo" => 123, "bar" => null]
myFunc(["bar" => "baz"]);  // Prints: ["foo" => 123, "bar" => "baz"]
myFunc(["baz" => 234]); // This will cause an exception, because the key "baz" is not known

简单定义

如上所示,您可以定义一个简单的键列表和相应的默认值,它们的作用类似于 "array_merge"。传递给 $options 的所有不在定义中的键将抛出验证异常。一般来说,您可以传递任何值作为默认值(数组需要一点技巧,见下文);

定义数组作为默认值

请注意,无法像其他类型一样传递数组作为默认值。您必须确保您的默认数组被一个外部的数组包围,如下所示

use Neunerlei\Options\Options;
$options = Options::make($options, [
    "foo" => [["my" => "defaultValue"]]
]);

如果您没有将默认数组包裹在数组中,将抛出 InvalidOptionDefinitionException。

高级定义

除了简单的默认值之外,您还可以在定义数组中使用数组作为值。在其中,您可以设置以下选项以验证并按需处理选项。

我选择数组作为定义,因为它们运行速度快,只需要记住少量选项。

选项

default (mixed|callable)

这是当 $options 中的键未指定时使用的默认值。如果未设置,则选项键是必需的!如果默认值是闭包,则调用闭包,并使用其结果作为值。

use Neunerlei\Options\Options;

// Simple value default
$options = Options::make($options, [
    "foo" => [
        "default" => 123
    ]
]);

// Closure result value default
$options = Options::make($options, [
    "foo" => [
        "default" => function($key, $options, $node, $context){
            return 123;
        }
    ]
]);

type (string|array)

允许对输入进行基本类型验证。它可以是字符串或字符串数组。如果提供了多个值作为数组,它们将通过 OR 运算符连接。可能的值包括

  • boolean
  • bool
  • true
  • false
  • integer
  • int
  • double
  • float
  • number (int and float)
  • numeric (both int and float + string numbers -> is_numeric)
  • string
  • resource
  • null
  • callable

还可以根据类或接口名称验证实例的类型。

use Neunerlei\Options\Options;

// Simple types
$options = Options::make($options, [ "foo" => [ "type" => "string" ] ]);
$options = Options::make($options, [ "foo" => [ "type" => "number" ] ]);
$options = Options::make($options, [ "foo" => [ "type" => [ "number", "string" ] ] ]);

// Class types
interface AI {};
class A implements AI {}
class B extends A {}
$options = Options::make(["foo" => new A()], [ "foo" => [ "type" => [A::class]]]); // OK -> Same class
$options = Options::make(["foo" => new B()], [ "foo" => [ "type" => [A::class]]]); // OK -> A is the parent
$options = Options::make(["foo" => new B()], [ "foo" => [ "type" => [AI::class]]]); // OK -> AI is implemented by the parent
$options = Options::make(["foo" => new A()], [ "foo" => [ "type" => [B::class]]]); // FAIL

preFilter (callable)

在类型验证之前调用的回调。可用于在验证类型之前转换传入的值。

use Neunerlei\Options\Options;
$options = Options::make($options, [
    "foo" => [
        "preFilter" => function($incomingValue, $key, $options, $node, $context){
            if(is_string($incomingValue)) {return (int)$incomingValue;}
            return $incomingValue;
        }
    ]
]);

filter (callable)

在类型验证完成后调用的回调。可用于在自定义验证开始之前处理给定的值。

use Neunerlei\Options\Options;
$options = Options::make($options, [
    "foo" => [
        "type" => "int",
        "filter" => function(int $incomingValue, $key, $options, $node, $context){
            return empty($incomingValue) ? 1 : $incomingValue;
        }
    ]
]);

validator (callable)

执行给定的可调用对象。函数接收:$value, $key, $options, $node, $context。

  • 如果函数返回 FALSE,则验证失败。
  • 如果函数返回 TRUE,则验证通过。
  • 如果函数返回值数组,则将值传递并像传递给 "validator" 的数组一样处理。
  • 如果函数返回字符串,则视为自定义错误消息。
use Neunerlei\Options\Options;
$options = Options::make($options, [
    "foo" => [
        "type" => "int",
        "validator" => function(int $incomingValue, $key, $options, $node, $context){
            return TRUE; // Success!
            return FALSE; // Failed
            return "Failed to validate something!"; // Failed with custom error message
            return [123, 234]; // Let the "values" validator decide (see: validator (array))
        }
    ]
]);

validator (string)

如果给定的值是非可调用的字符串,则将其评估为正则表达式

use Neunerlei\Options\Options;
$options = Options::make($options, [
    "foo" => [
        "type" => "string",
        "validator" => '~^0-9$~'
    ]
]);

validator (array)

一个基本的验证程序,接收一个可能的值列表,并检查给定的值是否与其中至少一个匹配(或运算符)。

use Neunerlei\Options\Options;
$options = Options::make($options, [
    "foo" => [
        "type" => "int",
        "validator" => [123, 234] // Only 123 or 234 are allowed values
    ]
]);

子元素 (数组)

这可以用来对选项树应用嵌套定义。`children` 定义的方式与根级别完全相同。只有当 $options 中的值是数组(或默认值为空数组)时,才会使用子元素。有三种方法来评估子元素

  1. 验证节点的一个直接、关联的子元素
use Neunerlei\Options\Options;
$options = Options::make([], [
    "foo" => [
        "type" => "array",
        "default" => [],
        "children" => [
            "childFoo" => 123,
            "KongFoo" => [
                "type" => "string",
                "default" => "foo!"
            ]
        ]
    ]
]);

// $options will look like:
// [
//     "foo" => [
//         "childFoo" => 123,
//         "KongFoo" => "foo!"
//     ]
// ]
  1. 验证具有相同结构的子节点列表
use Neunerlei\Options\Options;
$options = [
    "foo" => [
        ["childFoo" => 234],
        ["KongFoo" => "bar :D"]
    ]
];

$options = Options::make($options, [
    "foo" => [
        "type" => "array",
        "default" => [],
        "children" => [
            // This asterisk defines, that the children are repeatable
            "*" => [
                "childFoo" => 123,
                "KongFoo" => [
                    "type" => "string",
                    "default" => "foo!"
                ]
            ]
        ]
    ]
]);

// $options will look like:
// [
//     "foo" => [
//         ["childFoo" => 234, "KongFoo" => "foo!"],
//         ["childFoo" => 123, "KongFoo" => "bar :D"]
//     ]
// ];
  1. 验证具有相同类型的值列表(例如电话号码列表)
use Neunerlei\Options\Options;
$options = [
    "foo" => [
        'HOW',
        'ARE',
        'YOU'
    ]
];

$options = Options::make($options, [
    "foo" => [
        "type" => "array",
        "default" => [],
        "children" => [
            // This hashtag defines, that we expect repeatable children of the same type
            "#" => [
                'type' => 'string',
                'filter' => function(string $v): string{
                    return strtolower($v);
                }
                'validator' => ['how', 'are', 'you']
            ]
        ]
    ]
]);

// $options will look like:
// [
//     "foo" => [
//        'how', 'are', 'you'
//     ]
// ];

布尔标志

还可以提供类型为 "boolean" 的选项作为 "flags",这意味着你不需要提供任何值给它。注意:布尔标志只能用于将布尔值设置为 TRUE;如果你想将其设置为 FALSE,你必须设置键值对。

use Neunerlei\Options\Options;
function myFunc(array $options = []){
    // Apply the options
    $options = Options::make($options, [
        "foo" => [
            "type" => "bool",
            "default" => false
        ]
    ]);
    print_r($options);
}

myFunc(); // Prints: ["foo" => false]
myFunc(["foo"]); // Prints: ["foo" => true]
myFunc(["foo" => true]); // Prints: ["foo" => true]

附加选项

Options::make() 方法的第三个参数允许你定义附加选项。所有布尔值都可以作为键值对或布尔标志传递。

allowUnknown (布尔)

默认值:FALSE

如果设置为 TRUE,未知键将被保留在结果中。

ignoreUnknown (布尔)

默认值:FALSE

如果设置为 TRUE,未知键将被忽略并从结果中删除。

allowBooleanFlags (布尔)

默认值:TRUE

如果设置为 FALSE,则不允许在输入数组中使用布尔标志。这在验证 API 输入时很有用。

单值处理

通常,这与 Options::make() 做的是相同的事情,但它旨在验证非数组选项。

注意:有一个陷阱。正如你在我们的示例中所看到的,我们在签名中将 $anOption 定义为 = null。这会导致方法使用默认值 "foo",如果属性未设置。所以请确保,如果你想允许 NULL 作为非默认值,请使用回调作为默认值并自行处理 NULL。

use Neunerlei\Options\Options;
function myFunc($value, $anOption = null){
   $anOption = Options::makeSingle("anOption", $anOption, [
       "type" => ["string"],
       "default" => "foo",
   ]);
}

不使用静态类的方法

静态类使用 Neunerlei\Options\Applier\Applier 类的单例来执行所有操作。所以如果你想使用 applier 作为服务并通过依赖注入使用,只需使用 applier 类而不是静态的 Options 类。

扩展 applier 类

静态 Options 类有一个公共、静态属性 $applierClass,它定义了用于逻辑的类的名称。如果你想扩展功能,你可以简单地扩展 applier 类并将 Options::$applierClass 设置为你的扩展类的名称,然后一切就绪。

特别感谢

特别感谢 LABOR.digital(这是德语中的实验室,而不是英语中的“工作” :D)的人们,使他们能够在线发布我的代码。

明信片软件

你可以自由使用这个包,但如果它进入了你的生产环境,我非常希望你能从你的家乡寄给我一张明信片,说明你正在使用我们的哪个包。

你可以在这里找到我的地址:这里

谢谢 :D