grithin/php-conform
Composer 安装命令:
composer require grithin/php-conform
包简介
PHP Input Conform Handler
README 文档
README
Ordered filtering and validation with standard input logic.
About
Back around 2009, I wanted to build something that would resolve having to code the normal input logic in situations like
- if x field failed, don't check y field
- if x field failed one step of validation, don't validate it further
- if x field failed validation, stop validating all input and return with error
There are a lot of combinations of this input field dependent logic which I thought could be simplified in expression. So, I created this class, which uses logic flags.
Use
Smallest Example
# 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 }
Setting The Input
# 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.
Using Default Conformers
There are three conformers that come auto-attached to a Conform instance: \Grithin\Conform\Filter, \Grithin\Conform\Validate, and \Grithin\Conform\GlobalFunction. These are represented in rules by the prefixes f, v, and g.
To filter an input to an int, you can use f.int, but to validate the input is an int, you would use v.int. Filter and validate can be used in conjuction because the value passed to a proceeding rule is the output from the preceeding rule. For instance, we can filter to digits, and then check if the result is a valid 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 is used to reference a global function.
$rules = ['age'=>'g.strtoupper'];
(The $Conform parameter will not be passed to the global function)
Adding Conformers
Use the conformer_add function.
$Conform->conformer_add($string_identity, $pathed_callable);
The pathed callable must be callable at the path provided by the rule (according to lodash style pathing for _.get)
The callable receives the $Conform instance as the final parameter.
You can add various types of conformers
# 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)
Using Flags
Form validation logic mostly follows patterns.
For example, if the id input is an int, check it in the database:
$rules = ['id' => `!v.int, db.check`];
The ! says, ensure id input exists as an int before proceeding to the following rules on the field. In this way, we don't attempt to check the database with input that might be some arbitrary string.
What if we had multiple fields that relied on resolving a user id? You can exit out of validation entirely:
$rules = [ 'id' => `!!v.int, !!db.check`, 'name' => 'db.matches_id' ];
Here, the !! says, if id is not an int, exit with fail and parse no more fields. And if db.check fails, also exit with fail.
Sometimes there are optional fields that we still want to filter if they are present. To do this, you can combine two prefixes.
$rules = [ 'email' => `?!v.filled, v.email`, ];
This says, if the field is not filled, stop applying the rule, but don't show as an error. This way, if the user left the field empty, there will be no email validation and no error, but if the user had filled out the email input, there will be email validation. (The order of ! and ? doesn't matter.)
Special Cases
There are prefixes for some rarer cases.
What if we wanted to collect multiple validation errors for a field, but then not process some ending rules b/c of the errors?
$rules = [ 'email' => `v.filled, v.email, &db.check`, ];
If the email field were not filled, this field rule set would result in an error for not being filled and an error for not validating as an email. The & prefix indicates, if there were any errors in the previous part of the rule chain, stop execution of rules for the field.
This can similarly be done for the entire form. What if we wanted to collect errors across multiple fields, but wanted the presence of those errors to prevent some ending rule exectuion?
$rules = [ 'id' => `!v.int, db.check`, 'name' => 'v.name, &&db.matches_id' ];
Here, by use of the &&, if there were any errors in any of the previous chain or previous fields, the proceeding rule will not execute.
Finally, some times the reverse of a rule is desired. For instance, what if I wanted an email that was unique in the database but I just has a email_exists conformer function?
$rules = [ 'email' => `~db.email_exists`, ];
Here, the ~ is like a "not", and indicates a lack of error indicates an error.
Rule Format And Parameters
Parameters may be passed to a conformer in addition to the value of the input.
$rules = ['age'=>'!v.range|18;60'];
Here we see the | separates the parameters from the function path, and the ; separates the parameters from themselves.
This form is the short form. Sometimes the use of ! or ; can be problematic, so there are long forms
# 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]]];
Note, with the array separated callable, the function itself can be a callable instead of a path.
$rules = [ 'age'=>[ [['!', function(){}], 18, 60]] ];
Retrieving Partial Output
Although get returns false if there were any errors, the Conform output for the fields that did not have errors is available with $Conform->output
$input = ['name' => 'bob', 'age' => 2]; $Conform = new Conform($input); $conformed = $Conform->get(['name'=>'v.int', 'age'=>'v.int']); # > false $Conform->output; # > ['age'=>2]
Using The Errors
Errors are available from Conform and in the form of \Grithin\Conform\Error
$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', ) */
The error objects can be used as arrays. There are three properties
- type
- message
- fields
It is left up to the implementor to change the message of the built in validation errors.
You can select the field or fields you want the errors for
//... # 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']);
Making Validation
Within a conformer, you can signal an error
$conformer = function($v, $Conform){ $Conform->error('Error Message'); return $v; }; $Conform->conformer_add('conformer', $conformer);
A few things to note here
- the $Conform instance is passed in as the last parameter to the conformer function
- you can still return the value, even when there is an error, so that further validation can be done
By default, the error type will be whatever the path to the validator function was. But, you set your own type, and you can even specify the fields if the error is linked to multiple.
$conformer = function($v, $Conform){ $error = [ 'message' => 'Error Message', 'type' => 'custom_type', 'fields' => ['name', 'age'] ]; $Conform->error($error); return $v; }; $Conform->conformer_add('conformer', $conformer);
The current field is added into the fields array.
Context Data
Sometimes it is useful to know context data within a conform function. To access context data, you can use the $Conform instance that is passed in as the last parameter to conformer functions.
The context data that is useful:
->fieldthe current field that is being conformed->outputthe current output of the conform process (ie, fields that have been conformed)->inputthe current input
Let's use a conformer that relies on the output of a previous field (field must come prior), and the input of another field
$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; };
Validate And Filter Alone
You can use Validate and Filter pseudo statically, b/c they are traited with SingletonDefault.
Filter::init()->url($url) Validate::init()->test('url', $url);
Rule Item Prefixes
The prefix can be some combination of the following
- "!" to break on error with no more rules for that field should be applied
- "!!" to break on error with no more rules for any field should be applied
- "?" to indicate the validation is optional, and not to throw an error (useful when combined with '!' => '?!v.filled,email')
- "~" to indicate if the validation does not fail, then there was an error. Note, the original value (passed in to the function) will be pushed forward
- "&" to indicate code should break if there were any previous errors on that field
- "&&" to indicate code should break if there were any previous errors on any field in the validate run
grithin/php-conform 适用场景与选型建议
grithin/php-conform 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 94 次下载、GitHub Stars 达 0, 最近一次更新时间为 2016 年 08 月 03 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「php input get post filter validate」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 grithin/php-conform 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 grithin/php-conform 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 grithin/php-conform 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Yii2 map input widget. Allows you to select geographcal coordinates via a human-friendly inteface.
Widget to add a remaining character counter to text inputs and textareas
Native (browser) color input field for SilverStripe
Integration bundle for Aura.Input with Aura.Filter
phpABLE file-system library
Get Address IO wrapper covering all endpoints available from the API.
统计信息
- 总下载量: 94
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 2
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: Apache-2.0
- 更新时间: 2016-08-03