Mojolicious::Plugin::Vparam - Mojolicious plugin validator for GET/POST data.



  • Simple syntax or full featured

  • Many predefined types

  • Shortcuts for the most common uses

  • Filters complementary types

  • Support arrays and hashes of values

  • Support HTML checkbox as bool

  • Simple JSON values extraction and validation using JSON Pointer from Mojo::JSON::Pointer.

  • Simple XML/HTML values extraction and validation using CSS selector engine from Mojo::DOM::CSS or XPath from XML::LibXML.

  • Support objects via parameters

  • Validate all parameters at once and get hash to simple use in any Model

  • Manage validation errors

  • Full Mojolicious::Validator::Validation integration

This module use simple parameters types str, int, email, bool, etc. to validate. Instead of many other modules you mostly not need add specific validation subs or rules. Just set parameter type. But if you want sub or regexp you can do it too.


    # Add plugin in startup

    # Use in controller
    $login      = $self->vparam(login    => 'str');
    $passw      = $self->vparam(password => 'password', size     => [8, 100]);
    $email      = $self->vparam(email    => 'email',    optional => 1);
    $session    = $self->vparam(session  => 'bool',     default  => 1);

    $ids        = $self->vparam(ids => '@int');



Get one parameter. By default parameter is required.

    # Simple get one parameter
    $param1 = $self->vparam(date => 'datetime');

    # Or more syntax
    $param2 = $self->vparam(count => {type => 'int', default => 1});
    # Or more simple syntax
    $param2 = $self->vparam(count => 'int', default => 1);


Get many parameters as hash. By default all parameters are required.

    %params = $self->vparams(
        # Simple syntax
        name        => 'str',
        password    => qr{^\w{8,32}$},
        myparam     => sub { $_[1] && $_[1] eq 'ok' ? 1 : 0 } },
        someone     => ['one', 'two', 'tree'],

        # More syntax
        from        => { type   => 'date', default => '' },
        to          => { type   => 'date', default => '' },
        id          => { type   => 'int' },
        money       => { regexp => qr{^\d+(?:\.\d{2})?$} },
        myparam     => { post   => sub { $_[1] && $_[1] eq 'ok' ? 1 : 0 } },

        # Checkbox
        isa         => { type => 'bool', default => 0 },


Like vparams but add some keys to simple use with tables. Example:

    # HTML - table with controls and filters
    Order by:
    <select name="oby">
        <option value="0">Name</option>
        <option value="1">Date</option>
    Order direction:
    <select name="ods">
        <option value="asc">Low to High</option>
        <option value="desc">High to Low</option>
    Count per page:
    <select name="rws">
        <option value="10">10</option>
        <option value="100">100</option>
    Filter by name:
    <input type="text" name="name" value="">
    Any other filters ...

    # Controller
    %params = $self->vsort(
        -sort       => ['name', 'date', ...],

        # next as vparams
        name        => 'text',

Page number. Default: 1.

You can set different name by vsort_page config parameter. If you set undef then parameter is not apply.


Rows on page. Default: 25.

You can set different name by vsort_rws config parameter. You can set different default by vsort_rows config parameter. If you set undef then parameter is not apply.


Column number for sorting. Default: 1 - in many cases first database column is primary key.

You can set different name by vsort_oby config parameter. If you set undef then parameter is not apply.

Value of oby The value will be automatically mapped to the column name using the "-sort" attribute. Also, the value will be checked for proper mapping. So you do not need to worry about it.


Sort order ASC|DESC. Default: ASC.

You can set different name by vsort_ods config parameter. If you set undef then parameter is not apply.

verror $name

Get parameter error string. Return 0 if no error.

    # Get error
    print $self->verror('myparam');

    # Get error for first element in array
    print $self->verror('myparam' => 0);

    # Set error
    $self->verror('myparam', message => 'Error message')


Return errors count in scalar context. In list context return errors hash.

    # List context get hash
    my %errors = $self->verrors;

    # Scalar context get count
    die 'Errors!' if $self->verrors;

vclass $name, @classes

Get classes for invalid input. Return empty string if no error.

    # Form example
    <input name="myparam" class="<%= vclass 'myparam' %>">
    # Return next code for invalid I<myparam>:
    # <input name="myparam" class="field-with-error">

You can set additional @classes to set if field invalid.

vvalue $name, $default

Get raw input value after validation. Return $default value or empty string before validation.

    # Form example:
    <input name="myparam" value="<%= vvalue 'myparam' %>">

    # Return next code if user just open form without submit and validation:
    # <input name="myparam" value="">

    # Then user submit form and you validate id. For example user submit "abc":
    # <input name="myparam" value="abc">

vtype $name, %opts

Set new type $name if defined %opts. Else return type $name definition.

    # Get type

    # Set type
    # load  - requires modules
    # pre   - get int
    # valid - check for not empty
    # post  - force number
        pre     => sub {
            my ($self, $param) = @_;
            return int $param // '';
        valid   => sub {
            my ($self, $param) = @_;
            return length $param ? 0 : 'Invalid'
        post    => sub {
            my ($self, $param) = @_;
            return 0 + $param;

vfilter $name, &sub

Set new filter $name if defined %opts. Else return filter $name definition.

    # Get filter

    # Set filter
    $self->vfilter('myfilter', sub {
        my ($self, $param, $expression) = @_;
        return $param eq $expression ? 0 : 'Invalid';

Filter sub must return 0 if parameter value is valid. Or error string if not.


You can use the simplified syntax instead of specifying the type, simply by using an expression instead.


Apply as "regexp" filter. No type verification, just match.

    $self->vparam(myparam => qr{^(abc|cde)$});
CODE $mojo, $value

Apply as "post" function. You need manual verify and set error.

    $self->vparam(myparam => sub { $_[1] && $_[1] eq 'good' ? 1 : 0 });

Apply as "in" filter. No type verification, just match.

    $self->vparam(myparam => [qw(abc cde)]);



CSS class for invalid parameters. Default: field-with-error.


You can simple add you own types. Just set this parameters as HashRef with new types definition.


You can simple add you own filters. Just set this parameters as HashRef with new filters definition.


Parameter name for current page number in vsort. Default: page.


Parameter name for current page rows count in vsort. Default: rws.


Default rows count for vsort_rws. Default: 25.


Parameter name for current order by vsort. Default: oby.


Parameter name for current order destination vsort. Default: ods.


Default order destination for vsort_rws. Default: ASC.


Phone country. Default: empty.


Phone region. Default: empty.


Name of algorithm to fix phone, typicallty country code. Default: empty.


Date format for strftime. Default: %F. if no format specified, return DateTime object.


Time format for strftime. Default: %T. if no format specified, return DateTime object.


Datetime format for strftime. Default: '%F %T %z'. if no format specified, return DateTime object.


By default return objects used for parse or validation: Mojo::URL, DateTime, etc.


By default all parameters are required. You can change this by set this parameter as true.


Secret for address:points signing. Format: "ADDRESS:LATITUDE,LONGITUDE[MD5]". MD5 ensures that the coordinates belong to address.


Minimum password length. Default: 8.


Delimiter to split input parameter on two parts: key and value. Default: => - like a perl hash.


Enable Mojolicious::Validator::Validation integration.


List of supported types:


Signed integer. Use "min" filter for unsigned.

numeric or number

Signed number. Use "min" filter for unsigned.


Get money. Use "min" filter for unsigned.


Unsigned number: 0 <= percent <= 100.


Trimmed text. Must be non empty if required.


Any text. No errors.


String with minimum length from password_min. Must content characters and digits.


Standart 32 length UUID. Return in lower case.


Get date. Parsed from many formats. See date configuration parameter for result format. See DateTime::Format::DateParse and even more.


Get time. Parsed from many formats. See time configuration parameter for result format. See DateTime::Format::DateParse and even more.


Get full date and time. Parsed from many formats. See datetime configuration parameter for result format.

Input formats:

  • Timestamp.

  • Relative from now in format [+-] DD HH:MM:SS. First sign required.

    • Minutes by default. Example: +15 or -6.

    • Minutes and seconds. Example: +15:44.

    • Hours. Example: +3:15:44.

    • Days. Example: +8 3:15:44.

    Values are given in arbitrary range. For example you can add 400 minutes and 300 seconds: +400:300.

  • All that can be obtained DateTime::Format::DateParse.

  • Russian date format like DD.MM.YYYY


Boolean value. Can be used to get value from checkbox or another sources.

HTML forms do not send checbox if it checked off. So you don`t get error, but get false for it.

    $self->vparam(mybox => 'bool');

Valid values are:

  • TRUE can be 1, yes, true, ok

  • FALSE can be 0, no, false, fail

  • Empty string is FALSE

Other values get error.


    <input type="checkbox" name="bool1" value="yes">
    <input type="checkbox" name="bool2" value="1">
    <input type="checkbox" name="bool3" value="ok">


Three-valued logic. Same as bool but undef state if empty string. Example:

    <select name="logic1">
        <option value=""></option>
        <option value="1">True</option>
        <option value="0">False</option>


Email adress.


Get url as Mojo::URL object.


Phone in international format. Support wait, pause and additional.

You can set default country phone_country and region phone_country codes. Then you users can input shortest number. But this is not work if you site has i18n.


JSON incapsulated as form parameter.


Location address. Two forms are parsed: string and json. Can verify adress sign to trust source.






International Securities Identification Number: Mir, American Express, Diners Club, JCB, Visa, MasterCard, Maestro, etc.

You can check for ISIN type like:

    # Mir
    $self->vparam(card => 'isin', regexp => qr{^2});

    # American Express, Diners Club, JCB
    $self->vparam(card => 'isin', regexp => qr{^3});

    # Visa
    $self->vparam(card => 'isin', regexp => qr{^4});

    # MasterCard
    $self->vparam(card => 'isin', regexp => qr{^5});

    # Maestro
    $self->vparam(card => 'isin', regexp => qr{^6});


Some local country, not 16 numbers cards: Maestro, Visa Electron, etc.


Aggregate any creditcard: ISIN, Maestro, etc.


Barcode: EAN-13, EAN-8, EAN 5, EAN 2, UPC-12, ITF-14, JAN, UPC, etc.

    $self->vparam(barcode => 'goods');


RU: Taxpayer Identification Number


RU: Code of reason for registration


Simple objects via parameters (without validation!). Example:

# {foo => [ {bar => 1, baz => 2} ]} ?param1[foo][0][bar]=1&param1[foo][0][baz]=2

This is experimental feature. We think how to validate parameters.


You can set a simple mode as in example or full mode. Full mode keys:


Default value. Default: undef.

    # Supress myparam to be undefined and error
    $self->vparam(myparam => 'str', default => '');


Autoload module for this type. Can be module name, array of module names or sub.

pre $mojo, &sub

Incoming filter sub. Used for primary filtration: string length and trim, etc. Result will be used as new param value.

Usually, if you need this attribute, you need to create a new type.

valid $mojo, &sub

Validation sub. Return 0 if valid, else string of error.

Usually, if you need this attribute, you need to create a new type.

post $mojo, &sub

Out filter sub. Used to modify value for use in you program. Usually used to bless in some object. Result will be used as new param value.


Parameter type. If set then some filters will be apply. See "TYPES".

    $self->vparam(myparam => 'datetime');
    $self->vparam(myparam => {type => 'datetime'});
        myparam1 => {type => 'datetime'},
        myparam2 => {isa  => 'datetime'},

After the application of the type used filters.

You can use isa alias instead of type.


Rename output key for vparams to simple use in models.

    # Return {login => '...', password => '...'}
        myparam1 => {type => 'str', as => 'login'},
        myparam2 => {type => 'str', as => 'password'},


Force value will array. Default: false.

You can force values will arrays by @ prefix or case insensive array[...].

    # Arrays shortcut syntax
    $param1 = $self->vparam(array1 => '@int');
    $param2 = $self->vparam(array2 => 'array[int]');

    # Array attribute syntax
    $param3 = $self->vparam(array3 => 'int', array => 1);

    # The array will come if more than one value incoming
    # Example:
    $param4 = $self->vparam(array4 => 'int');


Get value as hash. Default: false. You can get values as hash by % prefix.

To make hash vparam split value by predefined delimiter (see hash_delimiter configuration parameter). It`s important to make value format.

    # Get param1 as hash. Parameter value need to be like 'a=>1'.
    $param1 = $self->vparam(myparam1 => '%int');

    # Same, but custom delimiter "::"
    $param2 = $self->vparam(myparam2 => 'int', hash => '::');

    # Multiple parameters supported.
    # You can send many myparam3 with different values list like:
    # ?myparam3=a_1&myparam3=b_2&myparam3=c_3
    # and get perl hash like $param3 = {a => 1, b => 3, c => 3}
    $param3 = $self->vparam(myparam3 => '%int', hash => '_');


By default all parameters are required. You can change this for parameter by set optional. Then true and value is not passed validation don`t set verrors.

    # Simple vparam
    # myparam is undef but no error.
    $param1 = $self->vparam(param1 => 'int', optional => 1);

    # Set one in vparams
    %params = $self->vparams(
        myparam     => { type => 'int', optional => 1 },

    # Set all in vparams
    %params = $self->vparams(
        -optional   => 1,
        param1      => 'int',
        param2      => 'str',

    # Shortcut optional syntax
    $param2 = $self->vparam(param2 => '?int');
    $param3 = $self->vparam(param3 => 'maybe[int]');
    $param4 = $self->vparam(param4 => 'optional[int]');

    # Shortcut required syntax
    $param5 = $self->vparam(param5 => '!int');
    $param6 = $self->vparam(param6 => 'require[int]');
    $param7 = $self->vparam(param7 => 'required[int]');


So as not to smear the validation code you can use the skip parameter to skip on the condition. This attribute is useful for controlling access to the form fields.

    # This example don`t get param1 in production mode.

    # HTML
    % unless( $self->app->mode eq 'production' ) {
        %= number_field 'param1'
    % }

    # Simple flag
    $param1 = $self->vparam(
        param1      => 'int', skip => $self->app->mode eq 'production',

    # Same as by use sub.
    $param1 = $self->vparam(
        param1      => 'int', skip => sub { $_[0]->app->mode eq 'production' },

If you use sub then first parameter is controller.


By default all parameters are in output hash. You can skip parameter in result if it`s undefined by set skipundef.

    # Simple vparam
    # myparam is undef.
    $param1 = $self->vparam(param1 => 'int', optional => 1, skipundef => 1);

    # Simple flag
    # The %params hash is empty if myparam value is not integer.
    %params = $self->vparams(
        myparam     => { type => 'int', optional => 1, skipundef => 1 },

    # Set all in vparams
    # The %params hash is empty if all parameters are not valid.
    %params = $self->vparams(
        -skipundef  => 1,
        param1      => 'int',
        param2      => 'str',

    # Shortcut syntax: skipundef and optional is on
    $param2 = $self->vparam(param2 => '~int');

Arrays always return as arrayref. But undefined values will be skipped:

    # This vparam return [1,2,3] for ?param3=1&param3=&param3=2&param3=3
    $param2 = $self->vparam(param3 => '~int');


You can simple split textarea to values:

    # This vparam return [1,2,3] for input "1\n2\n3\n"
    $param1 = $self->vparam(param1 => 'int', multiline => 1);

    # Or by custom regexp
    # This vparam return [1,2,3] for input "1,2,3"
    $param1 = $self->vparam(param1 => 'int', multiline => qr{\s*,\s*});

Empty lines ignored.


Any array values can be joined in string:

    # This vparam return "1,2,3" for input ?param1=1&param1=2&param1=3
    $param1 = $self->vparam(param1 => 'int', multijoin => ',');

    # This vparam return "1,2,3" for input "1\n2\n3\n"
    $param2 = $self->vparam(param2 => 'int', multiline => 1, multijoin => ',');


Keep and return blessed object for parsed parameters if available. Vparam always return scalars if disabled.

Note: if defined date, time, datetime then always return formatted scalar.

jpath or jpath?

If you POST data not form but raw JSON you can use JSON Pointer selectors from Mojo::JSON::Pointer to get and validate parameters.

    # POST data contains:
    # {"point":{"address":"some", "lon": 45.123456, "lat": 38.23452}}

    %opts = $self->vparams(
        address => { type => 'str', jpath => '/point/address' },
        lon     => { type => 'lon', jpath => '/point/lon' },
        lat     => { type => 'lat', jpath => '/point/lat' },

Note: we don`t support multikey in json. Use hash or die.

If You use jpath? instead jpath, vparam tries parse input json, if json is invalid vparam tries fetch param from input form:

    ######################## works:
    # {"point":{"address":"some", "lon": 45.123456, "lat": 38.23452}}

    # #######################works:
    # address=some&lon=45.123456&lat=38.23452

    ################# doesn't work:
    # query: address=some
    # body:  {"point":{"lon": 45.123456, "lat": 38.23452}}

    %opts = $self->vparams(
        address => { type => 'str', 'jpath?' => '/point/address' },
        lon     => { type => 'lon', 'jpath?' => '/point/lon' },
        lat     => { type => 'lat', 'jpath?' => '/point/lat' },

Note: You cant mix jpath and jpath?: If body contains valid JSON, vparam doesn't try check form params.


Same as jpath but parse XML/HTML using CSS selectors from Mojo::DOM::CSS.

    # POST data contains:
    # <Point>
    #    <Address>some</Address>
    #    <Lon>45.123456</Lon>
    #    <Lat>38.23452</Lat>
    # </Point>

    %opts = $self->vparams(
        address => { type => 'str', cpath => 'Point > Address' },
        lon     => { type => 'lon', cpath => 'Point > Lon' },
        lat     => { type => 'lat', cpath => 'Point > Lat' },


Same as cpath but parse XML/HTML using XPath selectors from XML::LibXML.

    # POST data contains:
    # <Point time="2016-11-25 14:39:00 +0300">
    #    <Address>some</Address>
    #    <Lon>45.123456</Lon>
    #    <Lat>38.23452</Lat>
    # </Point>

    %opts = $self->vparams(
        address => { type => 'str',         xpath => '/Point/Address' },
        lon     => { type => 'lon',         xpath => '/Point/Lon' },
        lat     => { type => 'lat',         xpath => '/Point/Lat' },
        time    => { type => 'datetime',    xpath => '/Point/@time' },


Same as jpath but apply for other types of object istead of JSON. See object type.



List of column names for vsort. Usually not all columns visible for users and you need convert column numbers in names. This also protect you SQL queries from set too much or too low column number.


Set default optional flag for all params in "vparams" and "vsort".


Set default skipundef flag for all params in "vparams" and "vsort".


Filters are used in conjunction with types for additional verification.


Check parameter value to be in range.

    # Error if myparam less than 10 or greater than 100
    $self->vparam(myparam => 'int', range => [10, 100]);


Check parameter to be match for regexp

    # Error if myparam not equal "abc" or "cde"
    $self->vparam(myparam => 'str', regexp => qr{^(abc|cde)$});


Check parameter value to be in list of defined values.

    # Error if myparam not equal "abc" or "cde"
    $self->vparam(myparam => 'str', in => [qw(abc cde)]);


Check maximum length in utf8.

    # Error if value is an empty string
    $self->vparam(myparam => 'str', size => [1, 100]);

Numbers comparation

min, max, equal, not

Strings comparation

lt, gt, le, ge, cmp, eq, ne


  • Version 1.0 invert valid behavior: now checker return 0 if no error or description string if has.

  • New errors keys: orig => in, pre => out


Mojolicious::Validator::Validation, Mojolicious::Plugin::Human.


Dmitry E. Oboukhov <>, Roman V. Nikolaev <>


Copyright (C) 2011 Dmitry E. Oboukhov <> Copyright (C) 2011 Roman V. Nikolaev <>

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.