NAME

Validator::Lazy

VERSION

Version 0.01

SYNOPSIS

use Validator::Lazy;

my $form = {
    first_name => 'John',
    last_name  => 'John',
    phone      => '+123456789',
    fax        => '',
    email      => 'john@site.com',
};

my $config = q~
    '/^(first|last)_name$/':
        - Trim: 'all'
        - Required
        - RegExp: '/^[A-Zaz]{3,64}$/'

    '[phone,fax]': Phone

    phone: Required

    email: [ 'Required', 'Email' ]

    myform:
        - Form: [ 'first_name', 'last_name', 'phone', 'fax', 'email' ]
~;

my $validator = Validator::Lazy->new( $config );

my $ok = $v->check(  myform => $form );  # true / false
OR
my ( $ok, $data ) = $validator->check( myform => $form );

use Data::Dumper;
say Dumper $v->errors;    # [ { code => any_error_code, field => field_with_error, data => { variable data for more accurate error definition } } ]
say Dumper $v->warnings;  # [ { code => any_warn_code,  field => field_with_warn,  data => { variable data for more accurate warn  definition } } ]
say Dumper $v->data;      # Fixed data. For example trimmed strings, corrected char case, etc...

For more details please see test files. For example t/14-int_roles-form.t can be the no.1 to see.

DESCRIPTION

Validator for different sets of data with easy and simple sets of rules.

Features:

  • Very simple and relatively short configuration

  • Allows to check almost everything: small web forms as well as deep multilevel structures with intersected params.

  • Some predefined check rules/roles ( Case, CountryCode, Email, Form, IP, IsIn, MinMax, Phone, RegExp, Required, Trim )

  • Easy way to create your own simple rules/roles and use them as native as predefined

  • No need to make and pass extra code to validator from caller during validation. Just a sets of rules.

  • No intersections and relations between rules (when you fix a one field validation, your other fields are be safe)

So, how it works...

Configuration/Init

my $v = Validator::Lazy->new( $config );

$config can be a string, or text, or hashref

  • when config is a string, which looks like a filename,- validator will try to read configuration from this file

  • when config is a text, validator will think, that it's a pure YAML or JSON and will try to parse it

  • when config is a hashref, validator just will apply it without further ado

In all cases, finnaly we have a hashref:

field_definition1:
    - rule1: param1
    - rule2: param2
    ...
field_definition2:
    ...

in case, when a field have 1 rule without params, we can give a scalar instead of Arrayref[HashRef]:

field_definition1: rule1

each rule can be an internal validator role, or external role, or a key from configuration

internal role example:

user_phone: Phone

external/your role example:

part_number: Where::Your::Role::IS::YourFieldRole

predefined role example:

# Here, we predefine/declare the new field: "any_phone"
any_phone: Phone

# And now we can use it within other field rules:
user_phone:
    - Required
    - any_phone

# And here we have alias or clone for any_phone
user_fax:  any_phone

each config key allows you to match more than one field of your data for checking:

for example we need to check a web form like this:

firstname:   'John'
lastname:    'John'
phone:       '+123456789'
fax:         ''
email:       'john@site.com'
secretkey:   'x1x2x3x4'

at first we make a config: firstname and lastname has equal requirements, so we put them in one key:

'[firstname,lastname]':
    - Required
    - RegExp: '/^[A-Zaz]{3,64}$/'

or like this

'/^(first|last)_name$/':
    - Required
    - RegExp: '/^[A-Zaz]{3,64}$/'

phone and fax has similar requirements, but phone is required and fax is optional:

[phone,fax]: Phone
phone: Required

and email:

email:
    - Required
    - Email

let's assume, that secretkey has some tricky checks, so it should be checked with external code. We should write a role (how to do this - see far below), and now just use it:

secretkey:
    - Required
    - Path::To::Your::Roles::SecretKey : { secretkey: param }

Combining all together, and we have:

# Config
my $config = q~
    '/(first|last)_name/':
        - Trim: 'all'
        - Required
        - RegExp: '/^[A-Zaz]{3,64}$/'

    '[phone,fax]': Phone

    phone: Required

    email:
        - Required
        - Email

    secretkey:
        - Required
        - 'Path::To::Your::Roles::SecretKey': { secretkey: 'param' }

    myform:
        - Form:
            - first_name
            - last_name
            - phone
            - fax
            - email
            - secretkey
~;

# Form to check:
my $form = {
    first_name => 'John',
    last_name  => 'John',
    phone      => '+123456789',
    fax        => '',
    email      => 'john@site.com',
    secretkey  => 'x1x2x3x4',
};

my $validator = Validator::Lazy->new( $config );

my $ok = $validator->check( $form ); # true
or
my ( $ok, $data ) = $validator->check( myform => $form );

Writing a roles

Let's write a role, that is required for example above:

package Path::To::Your::Roles::SecretKey;

use Modern::Perl;
use Moose::Role;

sub check {
    my ( $self, $value, $param ) = @_;

    $self;  # is a validator object
    $value; # is a value to check from form
    $param; # is a param = {secretkey:param}

    $self->add_error( ); # This will add to validator dafault error
    $self->add_error( 'CUSTOM_ERROR_CODE' );  # Custom error code will be plased instead of default
    $self->add_error( 'CUSTOM_ERROR_CODE', { some useful data } );  # Also, we can pass to error some data, and use it somwhere outside
    $self->add_error( { some useful data } );  # Default code, but some useful data

    $self->add_warning(); # All the same as with errors;

    return $value; # You should do it! Othervise you just lost your value.
}

# Also, you can use in check roles:
sub before_check { similar to check }
sub after_check { similar to check }
# They are working exactly as check, but allow to do some code separation

1;

Forms

Validator has a predefined "Form" role, let's, use it:

# YAML sample:
'/(first|last)_name/':
    - Trim: 'all'
    - Required
    - RegExp: '/^[A-Zaz]{3,64}$/'

full_name:
    Form: [first_name, last_name ]

Corrected example from above:

my $form = {
    full_name => {
        first_name => 'John',
        last_name  => 'Smith',
    },
    phone     => '+123456789',
    fax       => '',
    email     => 'john@site.com',
    secretkey => 'x1x2x3x4',
};

my $config = q~
    '/(first|last)_name/':
        - Trim: 'all'
        - Required
        - RegExp: '/^[A-Zaz]{3,64}$/'

    full_name:
        - Form: [first_name, last_name ]

    '[phone,fax]': Phone

    phone: Required

    email: Email

    secretkey:
        - Required
        - 'Path::To::Your::Roles::SecretKey': { secretkey: param }

    myform:
        - Form:
            - full_name
            - phone
            - fax
            - email
            - secretkey
~;

my $validator = Validator::Lazy->new( $config );

my $ok = $validator->check( $form ); # true

or

my ( $ok, $data ) = $validator->check( myform => $form );

warnings/errors/results

$validator->check( $data ); can return 1 or 2 params;

the 1st - can be true or false - is a result of check. the 2nd - form data, but corrected. For example, if Trim used, some strings will be trimmed from spaces.

after $validator->check() validators has:

$validator->errors - list = [ { code => 'SOME_ERROR_CODE', field => 'some_field', data => 'some data' }, ... ]
$validator->error_codes - list of codes = [ 'SOME_ERROR_CODE', ... ]

And all the same with warnings...

when an external role adds an error, then, by default it has a error/warning code:

role is "Path::To::Your::Roles::SecretKey"
default error code is PATH_TO_YOUR_ROLES_SECRETKEY_ERROR

when a subform adds an error, then default field name is generated as form_name + '_' + field_name:

myform:
    - Form:
        - full_name
            - Required

when full_name is absent, we have an error:

{ code => 'REQUIRED_ERROR', field => 'myform_full_name', data => {} }

Contestants

There are huge amount of other validators on CPAN.

All of them have their pros and cons, but all are very different.

I do not wish to write here detailed review of each, so let's just list them all:

https://metacpan.org/pod/Data::Validator

https://metacpan.org/pod/Validator::LIVR

https://metacpan.org/pod/QBit::Validator

https://metacpan.org/pod/Input::Validator

https://metacpan.org/pod/MojoX::Validator

https://metacpan.org/pod/Kossy::Validator

https://metacpan.org/pod/FormValidator::Tiny

https://metacpan.org/pod/FormValidator::LazyWay

METHODS

check $validator->check( $data );

SUPPORT AND DOCUMENTATION

After installing, you can find documentation for this module with the perldoc command.

perldoc Validator::Lazy

You can also look for information at:

    RT, CPAN's request tracker (report bugs here)
        http://rt.cpan.org/NoAuth/Bugs.html?Dist=Validator-Lazy

    AnnoCPAN, Annotated CPAN documentation
        http://annocpan.org/dist/Validator-Lazy

    CPAN Ratings
        http://cpanratings.perl.org/d/Validator-Lazy

    Search CPAN
        http://search.cpan.org/dist/Validator-Lazy/

AUTHOR

ANTONC <antonc@cpan.org>

LICENSE

This program is free software; you can redistribute it and/or modify it
under the terms of the the Artistic License (2.0). You may obtain a
copy of the full license at:

L<http://www.perlfoundation.org/artistic_license_2_0>