This document discusses the Data::FormValidator module, which provides a simplified way to validate form data in Perl. It allows defining validation profiles that specify required and optional fields, as well as custom and built-in constraint methods. The module takes request parameters, runs validation according to the profile, and returns results that can be easily integrated into templates to display error messages.
1. Data::FormValidator
Simplified
Fred Moyer
Red Hot Penguin Consulting LLC
http://redhotpenguin.com
2. The Form
update account name, email and password
current_email a hidden input with current email
3. The Request Args
A hash of request arguments, or a CGI like object with a
param() method akin to CGI::param
%req = ( email => ‘fred@slwifi.com’,
current_email => ‘foo@slwifi.com’,
passwd => ‘foo’,
retype => ‘foo’, );
4. Validation Profile
%profile = (
required => [qw( current_email email account )],
optional => [qw( password retype )],
constraint_methods => {
email => [
email(), # built in DFV constraint
not_current_user({ # function local to package
fields => [ 'email','current_email' ] }),
], # end email
password => SL::App::check_password({ # common validation
fields => [ 'retype', 'password' ],}),
},
);
5. Custom Validation
not_current_user()
sub not_current_user {
return sub {
my $dfv = shift;
my $val = $dfv->get_current_constraint_value;
my $data = $dfv->get_filtered_data;
my $email = $data->{email};
my $current = $data->{current_email};
return $val if ( $email eq $current ); # no change
my ($reg) =
SL::Model::App->resultset('Reg')->search( { email => $email } );
return if $reg; # oops existing user
return $val;
}
}
6. Custom Validation
SL::App::check_password
sub check_password {
return sub {
my $dfv = shift;
my $val = $dfv->get_current_constraint_value;
my $data = $dfv->get_filtered_data;
my $pass = $data->{password};
my $retype = $data->{retype};
return unless length($pass) > 5; # check length
return unless ($pass eq $retype); # check match
return $val;
}
}
7. Validation Execution
Apply the %profile to the %request arguments
$results = Data::FormValidator->check( %req, %profile );
9. Syntactic Sugar
Make the results object into a hash for ease of templating
if ( $results->has_missing or $results->has_invalid ) {
my $errors = $self->SUPER::_results_to_errors($results);
...
sub _results_to_errors {
my ( $self, $results ) = @_;
my %errors;
if ( $results->has_missing ) {
%{ $errors{missing} } = map { $_ => 1 } $results->missing;
}
if ( $results->has_invalid ) {
%{ $errors{invalid} } = map { $_ => 1 } $results->invalid;
}
return %errors;
}
10. Send Errors to Template
Hand the errors back to the template for display
%tmpl_data = (
errors => $errors,
...);
<label for="email" class="tip clear
[% IF errors.invalid.email or errors.missing.email %]error[% END %]
">Email address</label>
12. Useful Error Messages
Give the users a clue about what happened
[% IF errors %]<p class="error">Oops, correct the fields and try again.</p>[% END %]
[% IF errors.invalid.password %]<p class="error">Passwords didn’t match or too short</p>[% END %]
14. Quick Review
Multiple Constraints
User Defined Constraints
Email, etc. Validation Included
Easy Integration with CGI->params
or Hash Request Args
Easy Template Integration