Validator::Custom - Validates user input easily
Basic usages
# Load module and create object use Validator::Custom; my $vc = Validator::Custom->new; # Data used at validation my $data = {age => 19, name => 'Ken Suzuki'}; # Rule my $rule = [ age => [ 'int' ], name => [ ['not_blank', "Name must be exists"], [{length => [1, 5]}, "Name length must be 1 to 5"] ] ]; # Validate my $vresult = $vc->validate($data, $rule);
Result of validation
### Validator::Custom::Result # Chacke if the data is valid. my $is_valid = $vresult->is_valid; # Error messages my $messages = $vresult->messages; # Error messages to hash ref my $messages_hash = $vresult->messages_to_hash; # Error message my $message = $vresult->message('age'); # Invalid parameter names my $invalid_params = $vresult->invalid_params; # Invalid rule keys my $invalid_rule_keys = $vresult->invalid_rule_keys; # Raw data my $raw_data = $vresult->raw_data; # Result data my $result_data = $vresult->data;
Advanced features
# Register constraint $vc->register_constraint( email => sub { require Email::Valid; return 0 unless $_[0]; return Email::Valid->address(-address => $_[0]) ? 1 : 0; } ); # Multi parameters validation $data = {password1 => 'xxx', password2 => 'xxx'}; $vc->register_constraint( same => sub { my $values = shift; my $is_valid = $values->[0] eq $values->[1]; return [$is_valid, $values->[0]]; } ); $rule = [ {password_check => [qw/password1 password2/]} => [ ['same', 'Two password must be equal'] ] ]; $vresult = $vc->validate($data, $rule); # "OR" validation $rule = [ email => [ 'blank' ], email => [ 'not_blank', 'emai_address' ] ]; # Data filter $vc->data_filter( sub { my $data = shift; # Convert data to hash reference return $data; } ); # Register filter , instead of constraint $vc->register_constraint( trim => sub { my $value = shift; $value =~ s/^\s+//; $value =~ s/\s+$//; return [1, $value]; } );
Extending
### Extending Validator:Custom package YourValidator; use base 'Validator::Custom'; __PACKAGE__->register_constraint( $vc->register_constraint( email => sub { require Email::Valid; return 0 unless $_[0]; return Email::Valid->address(-address => $_[0]) ? 1 : 0; } ); 1;
Validator::Custom validates user input.
Can set a message for each parameter. the messages is added to the result when the paramter is invalid. the messages keeps the order.
Can register constraint function. such as "int", "defined". constraint function can receive any arguments, other than parameter value.
Can create original class, extending Validator::Custom (See Validator::Custom::HTMLForm)
Support multi-paramters validation, multi-values validation, OR condition validation.
Create a new Validator::Custom object.
use Validator::Custom; my $vc = Validator::Custom->new;
Data used in validation must be hash reference.
my $data = { age => 19, name => 'Ken Suzuki' };
Register constraint function. constraint must be sub reference, which check if the value is valid.
$vc->register_constraint( int => sub { my $value = shift; my $is_valid = $value =~ /^\d+$/; return $is_valid; }, not_blank => sub { my $value = shift; my $is_valid = $value ne ''; return $is_valid; }, length => sub { my ($value, $args) = @_; my ($min, $max) = @$args; my $length = length $value; my $is_valid = $length >= $min && $length <= $max; return $is_valid; }, );
Rule for validation has a specific format. the pairs of parameter name and constraint expressions. the format detail is explained in "4. Syntex of rule".
my $rule = [ age => [ 'int' ], name => [ ['not_blank', "Name must be exists"], [{length => [1, 5]}, "Name length must be 1 to 5"] ], # PARAMETER_NAME => [ # CONSTRIANT_EXPRESSION1 # CONSTRAINT_EXPRESSION2 # ] ];
Validate the data. validate() return Validator::Custom::Result object.
my $vresult = $vc->validate($data, $rule);
Validator::Custom::Result object has the result of validation.
Check if the data is valid.
my $is_valid = $vresult->is_valid;
Error messages
# Error messages my $messages = $vresult->messages; # Error messages to hash ref my $messages_hash = $vresult->messages_to_hash; # A error message my $message = $vresult->message('age');
Invalid paramter names and invalid result keys
# Invalid parameter names my $invalid_params = $vresult->invalid_params; # Invalid rule keys my $invalid_rule_keys = $vresult->invalid_rule_keys;
Raw data and result data
# Raw data my $raw_data = $vresult->raw_data; # Result data my $result_data = $vresult->data;
Examples:
Check the result and get error messages.
unless ($vresult->is_valid) { my $messages = $vresult->messages; # Do something }
Check the result and get error messages as hash reference
unless ($vresult->is_valid) { my $messages = $vresult->messages_to_hash; # Do something }
Combination with HTML::FillInForm
unless ($vresult->is_valid) { my $html = get_something_way(); # Fill in form $html = HTML::FillInForm->fill( \$html, $vresult->raw_data, ignore_fields => $vresult->invalid_params ); # Do something }
Basic syntax
Rule must be array reference. This is for keeping the order of invalid parameter names.
my $rule = [ ];
Rule contains the pairs of parameter name and list of constraint expression.
my $rule = [ name => [ 'not_blank' ], age => [ 'not_blank', 'int' ] # PARAMETER_NAME => [ # CONSTRIANT_EXPRESSION1 # CONSTRAINT_EXPRESSION2 # ] ];
Constraint expression
Constraint expression is one of four.
constraint name
CONSTRAINT_NAME
constraint name and message
[CONSTRIANT_NAME, MESSAGE]
constraint name and argument
{CONSTRAINT_NAME => ARGUMENT}
constraint name and argument and message
[{CONSTRAINT_NAME => ARGUMENT}, MESSAGE]
Example:
my $rule = [ age => [ # 1. constraint name 'defined', # 2. constraint name and message ['not_blank', 'Must be not blank'], # 3. constraint name and argument {length => [1, 5]}, # 4. constraint name and argument and message [{regex => qr/\d+/}, 'Invalid string'] ] ];
Multi-paramters validation
Multi-paramters validation is available.
$data = {password1 => 'xxx', password2 => 'xxx'}; $rule = [ {password_check => [qw/password1 password2/]} => [ ['duplication', 'Two password must be equal'] ] ];
"password1" and "password2" is parameter names. "password_check" is result key.
Multi-values validation
Multi-values validation is available if the paramter value is array reference. Add "@" mark before constraint name.
$data = { nums => [1, 2, 3] }; $rule = [ 'nums' => [ '@int' ] ];
Validation of OR condition
OR condition validation is available. Write paramter name repeatedly.
$rule = [ email => [ 'blank' ], email => [ 'not_blank', 'emai_address' ] ];
Shared rule
Can share rule with all parameters. Shared rule is added to the head of each list of constraint expression.
$vc->shared_rule([ ['defined', 'Must be defined'], ['not_blank', 'Must be not blank'] ]);
I explain the specification of constraint.
# Register constraint $vc->register_constraint( consrtaint_name => sub { my ($value, $args, $vc) = @_; # Do something return $is_valid; } )
Arguments and return value
Constraint function receive three arguments.
value
argument
Validator::Custom object
This is the value of data.
my $data = {name => 'Ken Suzuki'};
In this example, value is 'Ken Suzuki'
You can pass argument to consraint in the rule.
my $rule = [ name => [ {length => [1, 5]} ] ];
In this example, argument is [1, 5].
And this function must return a value to check if the value is valid.
In Multi-paramters validation, values is packed to array reference, value is ['xxx', 'xxx'].
Filtering function
Constraint function can be also return converted value. If you return converted value, you must return array reference, which contains two element, value to check if the value is valid, and converted value.
$vc->register_constraint( trim => sub { my $value = shift; $value =~ s/^\s+//; $value =~ s/\s+$//; return [1, $value]; } );
Validator::Custom is easy to extend. You can register constraint to Your class by register_constraint().
package YourValidator; use base 'Validator::Custom'; __PACKAGE__->register_constraint( defined => sub { defined $_[0] } ); 1;
Validator::Custom::Trim, Validator::Custom::HTMLForm is good examples.
Data filtering
If data is not hash reference, you can converted data to hash reference by data_filter().
$vc->data_filter( sub { my $data = shift; # Convert data to hash reference return $data; } );
Stock of messages
By default, all parameters is checked by validate(). If you want to check only if the data is valid, it is good to finish validation when the invalid value is found. If you set error_stock to 0, Validation is finished soon after invalid value is found.
$vc->error_stock(0);
constraints
$vc = $vc->constraints(\%constraints); $constraints = $vc->constraints;
Constraint functions.
error_stock
$vc = $vc->error_stock(1); $error_stock = $vc->error_stcok;
If error_stock is set to 1, all validation error is stocked. If error_stock is set 0, Validation is finished soon after a error occur.
Default to 1.
data_filter
$vc = $vc->data_filter(\&filter); $filter = $vc->data_filter;
Filter input data. If data is not hash reference, you can convert the data to hash reference.
$vc->data_filter( sub { my $data = shift; # Convert data to hash reference. return $data; } )
rule
$vc = $vc->rule($rule); $rule = $vc->rule;
Rule for validation. Validation rule has the following syntax.
# Rule syntax my $rule = [ # 1. Validation rule is array ref key1 => [ # 2. Constraints is array ref 'constraint1_1', # 3. Constraint is string ['constraint1_2', 'error1_2'],# or arrya ref (message) {'constraint1_3' => 'string'} # or hash ref (arguments) ], key2 => [ {'constraint2_1' # 4. Argument is string => 'string'}, # {'constraint2_2' # or array ref => ['arg1', 'arg2']}, # {'constraint1_3' # or hash ref => {k1 => 'v1', k2 => 'v2'}}# ], key3 => [ [{constraint3_1 => 'string'}, # 5. Combination argument 'error3_1' ] # and message ], { key4 => ['key4_1', 'key4_2'] } # 6. Multi-parameters validation => [ 'constraint4_1' ], key5 => [ '@constraint5_1' # 7. Multi-values validation ] ];
shared_rule
$vc = $vc->shared_rule(\@rule); $shared_rule = $vc->shared_rule;
Shared rule. Shared rule is added the head of normal rule.
syntax
$vc = $vc->syntax($syntax); $syntax = $vc->syntax;
Syntax of rule.
Validator::Custom inherits all methods from Object::Simple and implements the following new ones.
register_constraint
$vc->register_constraint(%constraint); $vc->register_constraint(\%constraint);
Register constraint. constraint must be sub reference, which check if the value is valid.
$vc->register_constraint( int => sub { my $value = shift; my $is_valid = $value =~ /^\-?[\d]+$/; return $is_valid; }, ascii => sub { my $value = shift; my $is_valid = $value =~ /^[\x21-\x7E]+$/; return $is_valid; } );
validate
$vresult = $vc->validate($data, $rule); $vresult = $vc->validate($data);
Validate the data. Return value is Validator::Custom::Result object. If the rule of second arument is ommited, rule attribute is used for validation.
defined
Check if the data is defined.
not_defined
Check if the data is not defined.
not_blank
Check if the data is not blank.
blank
Check if the is blank.
not_space
Check if the data do not containe space.
int
Check if the data is integer.
# valid data 123 -134
uint
Check if the data is unsigned integer.
# valid data 123
decimal
my $data = { num => '123.45678' }; my $rule => [ num => [ {'decimal' => [3, 5]} ] ]; Validator::Custom::HTMLForm->new->validate($data,$rule);
Each numbers (3,5) mean maximum digits before/after '.'
ascii
check is the data consists of only ascii code.
length
Check the length of the data.
The following sample check if the length of the data is 4 or not.
my $data = { str => 'aaaa' }; my $rule => [ num => [ {'length' => 4} ] ];
When you set two arguments, it checks if the length of data is in the range between 4 and 10.
my $data = { str => 'aaaa' }; my $rule => [ num => [ {'length' => [4, 10]} ] ];
http_url
Verify it is a http(s)-url
my $data = { url => 'http://somehost.com' }; my $rule => [ url => [ 'http_url' ] ];
selected_at_least
Verify the quantity of selected parameters is counted over allowed minimum.
<input type="checkbox" name="hobby" value="music" /> Music <input type="checkbox" name="hobby" value="movie" /> Movie <input type="checkbox" name="hobby" value="game" /> Game my $data = {hobby => ['music', 'movie' ]}; my $rule => [ hobby => [ {selected_at_least => 1} ] ];
regex
Check with regular expression.
my $data = {str => 'aaa'}; my $rule => [ str => [ {regex => qr/a{3}/} ] ];
duplication
Check if the two data are same or not.
my $data = {mail1 => 'a@somehost.com', mail2 => 'a@somehost.com'}; my $rule => [ [qw/mail1 mail2/] => [ 'duplication' ] ];
shift
Shift the head of array reference.
my $data = {nums => [1, 2]}; my $rule => [ nums => [ 'shift' ] ];
greater_than
Numeric comparison
my $rule = [ age => [ {greater_than => 25} ] ];
less_than
my $rule = [ age => [ {less_than => 25} ] ];
equal_to
my $rule = [ age => [ {equal_to => 25} ] ];
between
my $rule = [ age => [ {between => [1, 20]} ] ];
in_array
Check if the food ordered is in menu
my $rule = [ food => [ {in_array => [qw/sushi bread apple/]} ] ];
trim
Trim leading and trailing white space
my $rule = [ key1 => [ ['trim'] # ' 123 ' -> '123' ], ];
trim_lead
Trim leading white space
my $rule = [ key1 => [ ['trim_lead'] # ' abc ' -> 'abc ' ], ];
trim_trail
Trim trailing white space
my $rule = [ key1 => [ ['trim_trail'] # ' def ' -> ' def' ] ];
trim_collapse
Trim leading and trailing white space, and collapse all whitespace characters into a single space.
my $rule = [ key1 => [ ['trim_collapse'] # " \n a \r\n b\nc \t" -> 'a b c' ], ];
Please tell me the bugs.
<kimoto.yuki at gmail.com>
Validator::Custom and Validator::Custom::Result is now stable. all methods(except for experimantal marking ones) keep backword compatible in the future.
Yuki Kimoto, <kimoto.yuki at gmail.com>
http://github.com/yuki-kimoto/Validator-Custom
Copyright 2009 Yuki Kimoto, all rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
To install Validator::Custom, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Validator::Custom
CPAN shell
perl -MCPAN -e shell install Validator::Custom
For more information on module installation, please visit the detailed CPAN module installation guide.