NAME

Validator::Custom - Validates user input easily

SYNOPSYS

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'};

# Register constraint
$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
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

# 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(
    defined  => sub { defined $_[0] }
);

1;

DESCRIPTIONS

Validator::Custom validates user input.

1. Features

* 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.

2. Basic usages

Construct 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 list of constraint expression. the format detail is explained at 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);

3. Result of validation

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;

Example1: Check the result and get error messages.

unless ($vresult->is_valid) {
    my $messages = $vresult->messages;
    
    # Do something
}

Example2: Chack the result and get error messages as hash reference

unless ($vresult->is_valid) {
    my $messages = $vresult->messages_to_hash;

    # Do something
}

Example3: 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
}

4. Syntax of rule

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 is one of four.

1. constraint name

CONSTRAINT_NAME

2. constraint name and message

[CONSTRIANT_NAME, MESSAGE]

3. constraint name and argument

{CONSTRAINT_NAME => ARGUMENT},

4. constraint name and argument and message

[{CONSTRAINT_NAME => ARGUMENT}, MESSAGE]

Eample:

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 to constraint name.

$data = {
    nums => [1, 2, 3]
};

$rule = [
    'nums' => [
        '@int'
    ]
];

OR condition validation

OR condition validation is available. Write paramter name repeatedly.

$rule = [
    email => [
        'blank'
    ],
    email => [
        'not_blank',
        'emai_address'
    ]
];

(experimental) 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']
]);

5. Specification of constraint

I explain the specification of constraint.

Constraint function receive three arguments, 1. value, 2. argument, 3. Validator::Custom object.

And this function must return value to check if the value is valid.

# Register constraint
$vc->register_constraint(
    consrtaint_name => sub {
        my ($value, $args, $vc) = @_;
        
        # Do something
        
        return $is_valid;
    }
)

Three argument details

1. value

This is the value of data.

my $data = {name => 'Ken Suzuki'};

In this example, value is 'Ken Suzuki'

2. argument

You can pass argument to consraint in the rule.

my $rule = [
    name => [
        {length => [1, 5]}
    ]
];
In this example, argument is I<[1, 5]>.
3. Validator::Custom::Object

This is Validator::Custom::Object.

In corelative validation, values is packed to array reference, value is ['xxx', 'xxx'].

$data = {password1 => 'xxx', password2 => 'xxx'};

$rule = [
    {password_check => [qw/password1 password2/]} => [
        ['duplication', 'Two password must be equal']
    ]
];

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];
    }
);

6. Extending

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.

7. Advanced features

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;
    }
);

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);

ATTRIBUTES

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. Corelative validation
        => [
            'constraint4_1'
           ],
    key5 => [
        '@constraint5_1'              # 7. Multi-values validation
    ]
];

(experimental) shared_rule

$vc          = $vc->shared_rule(\@rule);
$shared_rule = $vc->shared_rule;

Shared rule. Shared rule is added the head of normal rule.

$vc->shared_rule([
    ['defined',   'Must be defined'],
    ['not_blank', 'Must be not blank']
]);

syntax

$vc     = $vc->syntax($syntax);
$syntax = $vc->syntax;

Syntax of rule.

MEHTODS

new

$vc = Validator::Costom->new;
$vc = Validator::Costom->new(%attributes);
$vc = Validator::Costom->new(\%attributes);

Construct a new Validator::Custom object.

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.

STABILITY

Validator::Custom and Validator::Custom::Result is now stable. all methods(except for experimantal marking ones) keep backword compatible in the future.

AUTHOR

Yuki Kimoto, <kimoto.yuki at gmail.com>

http://github.com/yuki-kimoto/Validator-Custom

COPYRIGHT & LICENCE

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.