grithin / php-conform
PHP 输入合规处理器
Requires
- php: >=5.5.9
- ext-pdo: *
- grithin/phpbase: ^5.0
This package is auto-updated.
Last update: 2024-09-09 02:01:25 UTC
README
使用标准输入逻辑进行排序过滤和验证。
关于
大约在2009年,我想构建一个东西,用于解决在以下情况中需要编写正常输入逻辑的问题:
- 如果x字段失败,则不检查y字段
- 如果x字段验证失败了一步,则不再进一步验证
- 如果x字段验证失败,则停止验证所有输入并返回错误
这种输入字段依赖逻辑有很多组合,我认为可以简化表达式。因此,我创建了这个类,它使用逻辑标志。
使用
最小示例
# Simplest example $Conform = new Conform(['age'=>' 10 ']); if($conformed = $Conform->get(['age'=>'f.int'])){ # in converting age to in, Conform has stripped the spaces echo $conformed['age']; # => 10 }
设置输入
# You can set the input either at construction or after $Conform = new Conform(['name'=>'bob']); $Conform->input(['name'=>'sue']); # if you do not provide an input on the construction (input value is false), Conform will use $_GET and $_POST as defaults, with $_POST overwriting colliding $_GET keys $_POST = ['name'=>'bob']; $Conform = new Conform(); $Conform->input(); # > ['name'=>'bob'] # if you want to set the input to the default input after construction, you can use the `request_input` method $Conform->input(Conform::request_input()); # the request_input has some additional logic about pulling input from the request that include both the use of a _json key and the handling of request type application/json. To see more, read the function doc.
使用默认合规器
有三个conformers
会自动附加到Conform实例:\Grithin\Conform\Filter
、\Grithin\Conform\Validate
和\Grithin\Conform\GlobalFunction。这些在规则中分别用前缀f
、v
和g
表示。
要将输入过滤为整数,可以使用f.int
,但为了验证输入是整数,则应使用v.int
。过滤和验证可以一起使用,因为传递给后续规则的值是前一个规则的输出。例如,我们可以过滤到数字,然后检查结果是否是有效的整数
$Conform = new Conform(['age'=>'bob']); $rules = ['age'=>'f.digits, v.int']; if($conformed = $Conform->get($rules)){ # ... }else{ echo 'did not validate'; } # > did not validate
g
用于引用全局函数。
$rules = ['age'=>'g.strtoupper'];
($Conform参数不会被传递给全局函数)
添加合规器
使用conformer_add
函数。
$Conform->conformer_add($string_identity, $pathed_callable);
路径调用必须在规则提供的路径上是可调用的(根据lodash风格的路径对_.get
进行路径解析)
调用接收$Conform实例作为最后一个参数。
您可以添加各种类型的合规器
# a closure $Conform->conformer_add('upper', function($x){ return strtoupper($x);}); $rules = ['name'=>'upper']; # an object with methods $Conform->conformer_add('f', new \Grithin\Conform\Filter); $rules = ['id'=>'f.int']; # a function reference $Conform->conformer_add('upper', 'strtoupper'); $rules = ['name'=>'upper']; # note, this will error b/c strtoupper does not expect 2 parameters ($Conform instance is passed as the last parameter)
使用标志
表单验证逻辑主要遵循模式。
例如,如果id输入是整数,则检查数据库
$rules = ['id' => `!v.int, db.check`];
其中的!
表示,在继续执行该字段的后续规则之前,确保id
输入存在且为整数。这样,我们就不会尝试使用可能是任意字符串的输入检查数据库。
如果我们有多个字段依赖于解析用户id,则可以完全退出验证
$rules = [ 'id' => `!!v.int, !!db.check`, 'name' => 'db.matches_id' ];
在这里,!!
表示,如果id
不是整数,则退出失败并解析更多字段。如果db.check
失败,也退出失败。
有时有一些可选字段,我们仍然希望过滤如果它们存在。为此,可以组合两个前缀。
$rules = [ 'email' => `?!v.filled, v.email`, ];
这表示,如果字段为空,则停止应用规则,但不会显示为错误。这样,如果用户留空该字段,则不会进行电子邮件验证并显示错误,但如果用户填写了电子邮件输入,则将进行电子邮件验证。(!
和?
的顺序不重要。)
特殊情况
有一些前缀用于一些较少见的情况。
如果我们想收集一个字段的多个验证错误,但又因为错误而不处理某些结束规则怎么办?
$rules = [ 'email' => `v.filled, v.email, &db.check`, ];
如果电子邮件字段为空,则此字段规则集将导致因未填写而出现错误,并因未验证为电子邮件而出现错误。&
前缀表示,如果规则链的前一部分有错误,则停止执行该字段的规则。
这可以类似地用于整个表单。如果我们想收集多个字段的错误,但又想阻止这些错误的产生阻止某些结束规则执行怎么办?
$rules = [ 'id' => `!v.int, db.check`, 'name' => 'v.name, &&db.matches_id' ];
在这里,通过使用&&
,如果前一个链或前一个字段中存在任何错误,后续规则将不会执行。
最后,有时可能希望得到一个规则的逆。例如,如果我想要一个在数据库中唯一的电子邮件,但我只有一个email_exists
验证函数呢?
$rules = [ 'email' => `~db.email_exists`, ];
在这里,~
就像一个“非”,表示没有错误表示存在错误。
规则格式和参数
除了输入值外,还可以将参数传递给验证函数。
$rules = ['age'=>'!v.range|18;60'];
在这里我们看到|
将参数与函数路径分开,而;
将参数彼此分开。这种形式是简短形式。有时使用!
或;
可能会有问题,因此存在长形式
# array seperated rules $rules = ['age'=>['!v.int', '!v.range|18;60']]; # array separated parameters $rules = ['age'=>[['!v.range', 18, 60]]]; # array separated callable $rules = ['age'=>[[['!', 'v.range'], 18, 60]]];
注意,使用数组分隔的可调用对象时,函数本身可以是可调用的,而不仅仅是路径。
$rules = [ 'age'=>[ [['!', function(){}], 18, 60]] ];
检索部分输出
虽然get
在存在错误时返回false,但通过$Conform->output
可以获取没有错误的字段的Conform输出。
$input = ['name' => 'bob', 'age' => 2]; $Conform = new Conform($input); $conformed = $Conform->get(['name'=>'v.int', 'age'=>'v.int']); # > false $Conform->output; # > ['age'=>2]
使用错误
错误以\Grithin\Conform\Error的形式从Conform中可用。
$input = ['year' => 'bob', 'age' => 2, 'number'=>'bill']; $Conform = new Conform($input); $conformed = $Conform->get([ 'year'=>'v.int', 'age'=>'v.int', 'number'=>'v.int' ]); foreach($Conform->errors() as $error){ var_export((array)$error); } /* array ( 'message' => 'v.int', 'fields' => array ( 0 => 'year', ), 'type' => 'v.int', )array ( 'message' => 'v.int', 'fields' => array ( 0 => 'number', ), 'type' => 'v.int', ) */
错误对象可以用作数组。有三个属性
- 类型
- 消息
- 字段
内置验证错误的消息更改由实现者决定。
您可以选择您想要的错误字段或字段。
//... # get all the errors for the field "year" $Conform->field_errors('year'); # get all the errors for the fields "year" and "number" $Conform->fields_errors(['year', 'number']);
制作验证
在验证函数内部,您可以发出错误信号
$conformer = function($v, $Conform){ $Conform->error('Error Message'); return $v; }; $Conform->conformer_add('conformer', $conformer);
以下是一些注意事项
- $Conform实例作为验证函数的最后一个参数传入
- 即使存在错误,您仍然可以返回值,以便进行进一步的验证
默认情况下,错误类型
将是验证函数的路径。但是,您可以设置自己的类型,并且如果错误与多个字段相关,您甚至可以指定字段。
$conformer = function($v, $Conform){ $error = [ 'message' => 'Error Message', 'type' => 'custom_type', 'fields' => ['name', 'age'] ]; $Conform->error($error); return $v; }; $Conform->conformer_add('conformer', $conformer);
当前字段被添加到字段数组中。
上下文数据
有时在验证函数中了解上下文数据很有用。要访问上下文数据,您可以使用作为验证函数最后一个参数传入的$Conform
实例。
有用的上下文数据
->field
正在验证的当前字段->output
当前验证过程的输出(即已验证的字段)->input
当前输入
让我们使用一个依赖于前一个字段输出(字段必须先于)和另一个字段输入的验证函数
$auth = function($v, $Conform){ $query = ['id'=>$Conform->output['id'], 'password'=>$conform->input['password']] if(!Db::check($query)){ $Conform->error('Password and id did not match'); } return $v; };
独立验证和过滤
由于它们具有SingletonDefault特性,因此可以使用Validate和Filter伪静态。
Filter::init()->url($url) Validate::init()->test('url', $url);
规则项目前缀
前缀可以是以下组合之一
- "!"在错误时断开,不应应用该字段的更多规则
- "!!"在错误时断开,不应应用任何字段的更多规则
- "?"表示验证是可选的,不要抛出错误(与'!'结合使用时很有用,例如'?!v.filled,email')
- "~"表示如果验证没有失败,则存在错误。注意,原始值(传递给函数的)将被推向前
- "&"表示如果该字段之前有错误,则应断开代码
- "&&"表示如果验证运行中任何字段有错误,则应断开代码