netom / colander
PHP输入过滤和验证库,具有功能化的特点
Requires
- php: >=5.5.0
Requires (Dev)
- phpunit/phpunit: >=4.6
README
Colander是一个PHP输入过滤和验证库,具有功能化的特点。
Colander允许你定义(输入)数据过滤和验证函数。在PHP或类似命令式、动态编程语言中,通常是通过定义一个领域特定语言(DSL),并使用该语言描述问题,通常使用字符串或文本文件(配置文件)来完成。
此类解决方案要么在速度方面表现不佳,要么很复杂。性能通常不佳,因为每次请求都必须解析配置,如果有人尝试缓存结果,可能会出现复杂性。
Colander通过不使用单独的DSL,而是定义一个EDSL(嵌入式DSL)来解决此问题,该DSL利用了PHP本身的功能。
描述数据验证的代码仍然看起来是声明性的,例如类似于配置文件而不是命令式程序,但它完全由原生PHP表达式组成。
因此,Colander带来了两个世界的最佳之处(第一个是配置文件领域,另一个是命令式检查这个和那个王国)。你可以拥有漂亮的数据过滤器和验证器(可以称为'处理器'吗)的描述,并且你的opcache将会很开心。
所以,
数据处理器描述看起来像什么样子?
让我们直奔主题
$processor = map([
'username' => seq([fMinLength(3), fmaxLength(64)]),
'age' => seq([fInteger(), fMin(13)])
]);
上面的表达式将$processor
变量赋值为一个函数。没错,这个变量将包含一个可以接受包含要验证的数据的单个参数并可以调用的函数。
Colander被设计成其所有生成的函数都没有任何副作用,也就是说:它不会打印或读取任何东西,不会设置全局变量等。这很重要,因为你可以将这些生成的函数重用多次,并且对于相同的输入,结果总是相同的。
让我们看一下上面的定义,但我相信你已经很清楚生成的函数将做什么。
工厂函数
在示例中,fMinLength
、fInteger
等是工厂。它们自身返回函数。
fInteger()
将返回一个函数,它接受一个参数,如果它是一个整数,则返回它,如果不是,则抛出ValidationException。
所有工厂函数都非常相似。它们接受一些(或没有)参数,然后返回一个验证或过滤函数(从现在起请称之为处理器)。
验证和过滤处理器
如果一个处理器返回其输入未更改,但可能会抛出异常,则称其为验证处理器。
一个过滤处理器可能会返回与输入不同的值。
使用处理器
上面的示例可以扩展如下
$processor = map([
'username' => seq([fMinLength(3), fmaxLength(64)]),
'age' => seq([fInteger(), fMin(13)])
]);
$valid_post = $processor($_POST);
由于PHP不允许尝试调用任意表达式的结果(比如,比如JavaScript做的),我们提供了一个方便的函数call()
,这样就可以在单个表达式中定义和使用处理器
$valid_post = call(map([
'username' => seq([fMinLength(3), fmaxLength(64)]),
'age' => seq([fInteger(), fMin(13)])
]), $_POST);
那么map()和seq()是什么意思?
是的,还有tpl()和lst()。
这些都是组合器。它们将现有的处理器组合成新的处理器。
看,处理器只是一个接受单个参数并返回值或抛出异常的函数。很简单,对吧?
这样的函数可以用来在你面前爆炸,如果你有一个太长的字符串,或者一个应该是整数的值,但它是一个数组。
检查表单字段或依次检查多个规则仍然有点复杂。不过,map()
和 seq()
正好能帮助你解决这些问题。
-
map()
是一个返回处理器的函数。它的输入是一个关联数组。数组中的每个字段都必须是处理器本身。由map()
生成的函数接受一个数组参数,并将处理器应用于相应的字段。因此,在上面的示例中,map()
组合器返回的处理器将检查通过它的任何数组中的 'username' 和 'age' 字段。 -
seq()
将返回一个处理器,它是传递给它的处理器数组的 序列。 -
tpl()
可用于验证 元组,即预定长度的数组,并且具有基于零的整数索引。它的参数是一个处理器数组,类似于seq()
,但它对每个相应的数组元素运行处理器,就像map()
会做的那样。 -
lst()
可用于处理相同类型数据的数组(如果你喜欢可以叫列表)。实际上,lst()
还可以在任何类型的可遍历对象上工作。
简单处理器
Colander 包含一系列简单处理器。几乎所有的 php is_* 函数都有 Colander 的对应函数(形式为 if*(使用驼峰命名法)和 fIs*(它是工厂函数))。
在所有这些函数都有文档说明之前,请参考源代码。
验证函数命名约定
is*:执行布尔检查的函数,如果结果为假,则抛出异常。
f*:工厂函数:返回函数的函数。例如:fIsNull 将返回 isNull 函数。
*_:该函数作用于值集合,并且有多个其他函数作用于集合成员。每个这些函数都可以抛出 ValidationExceptions。以 _ 结尾的函数在遇到第一个错误时停止。_ 总是在 S 之前(如果存在 S)。
*S:该函数作用于值集合。如果函数无法处理集合中的所有成员(因为数组太长或存在未检查的键),它将抛出 IncompleteValidationException(扩展 ValidationException)。