http://www.perlmonks.org?node_id=80037

Item Description: Helps the process of validating HTML forms

Review Synopsis:

I spend a lot of time writing perl to process HTML forms. I soon realized that I was writing very similar code in each case. Some common tasks of form validation include:

Data::FormValidator helps with all these tasks and more. Outside of the functions it provides, I find declaring the the form validation profile through it's interface to be useful. Here's the example from the documentation:
    {
        customer_infos => {
            optional     =>
                [ qw( company fax country ) ],
            required     =>
                [ qw( fullname phone email address city state zipcode ) ],
            constraints  =>
                {
                    email       => "email",
                    fax         => "american_phone",
                    phone       => "american_phone",
                    zipcode     => '/^\s*\d{5}(?:[-]\d{4})?\s*$/',
                    state       => "state",
                },
            defaults => {
                country => "USA",
            },
        },
        customer_billing_infos => {
             optional       => [ "cc_no" ],
             dependencies   => {
                "cc_no" => [ qw( cc_type cc_exp ) ],
             },
             constraints => {
                cc_no      => {  constraint  => "cc_number",
                                 params      => [ qw( cc_no cc_type ) ],
                                },
                cc_type => "cc_type",
                cc_exp  => "cc_exp",
              }
            filters       => [ "trim" ],
            field_filters => { cc_no => "digit" },
        },
    }
Any validation that you want to yourself you can add in, so you aren't limited to just the options that this module provides. Additionally, HTML::FormValidator doesn't force you to handle the form validations errors in any particular way. Instead it returns the results like this:
    my( $valids, $missings, $invalids, $unknowns ) =
        $validator->validate( \%fdat, "customer_infos" );
Here $valids will be a hash ref, and the other values will be array refs. A nice side effect of this arrangement is that if you've named your form fields with the same names as some database columns, you can now pass your $valids hash ref directly to a module like DBIx::Abstract to insert the results into a database, auto-quoting the values along the way.

Room for improvement

While I'm a fan of the module and find it very usable, it doesn't feel quite done yet. You can read and about my ideas to improve it.

An example

I've also put together an example of using Data::FormValidator for you to review. It demonstrates how you can use Data::FormValidator along with some other modules to easily display form validation results on the same page as the form, with the former values already filled in.

Replies are listed 'Best First'.
Re: Data::FormValidator
by mattr (Curate) on Apr 21, 2003 at 09:43 UTC
    I've rolled my own validators and fixed other people's validation code so many times I don't want to think about it.

    If the purpose of all of this is to keep people from reinventing the wheel here are some things you could do that would be really useful.

    - Why not concentrate on accumulating validation algorithms from people, unify them with documentation and provide them as plugins to your module and other people's modules?

    - ditto re browser compliant Javascript validation code. ditto also re good looking html templates.

    - consider reentrant forms possibly with encrypted hidden fields (see CGI::EncryptForm and CGI::FormBuilder).

    - Provide easy unit testing even from command line. It is difficult to test from command line even with perl -MCGI when you have a lot of fields, maybe some are from reenrant pages.

    - Providing a skeleton module for making new tests will help people reuse code and send back to you too.

    - Real world use may not be just a simple regex, business logic and ways to organize rules are more important (this is another whole ball 'o wax / module).

    - Even just a collection of validation subroutines which do not depend on each other and can be easily dropped in to one's code would be very helpful. Likewise, I have a lot of routines I've built up over various projects which I would have to drop in somewhere, e.g. email address validation, japanese phonetic conversions, local zipcode formats, double byte numbers, etc. So a way to add your own routines, and a set of tests for different data types to make sure they match, would also be good.

    - A homepage which lets people submit code (people can vote on it?) would be interesting.

    - Finally an easy way to set business logic rules would be useful.

      mattr,

      Thanks for your thorough and thoughtful feedback. I'd like to address some of your points:

      - Why not concentrate on accumulating validation algorithms from people, unify them with documentation and provide them as plugins to your module and other people's modules?

      D::FV now has good support for "plug-in" modules. Check the documentation for "validator_packages".

      - ditto re browser compliant Javascript validation code. ditto also re good looking html templates.

      I agree this would be useful but it's beyond the scope of this project. I know there are businesses out there that will sell you sets of attractive website templates, though.

      - consider reentrant forms possibly with encrypted hidden fields (see CGI::EncryptForm and CGI::FormBuilder).

      If you are a CGI::Application user, check out CGI::Application::ValidateRM for an easy way to re-fill a form with errors. It doesn't sound like it's a complete solution to what you want, though. This is also outside of the scope of D::FV,though. Support was added recently to return error messages in a more useful format. This will help some here.

      - Provide easy unit testing even from command line. It is difficult to test from command line even with perl -MCGI when you have a lot of fields, maybe some are from reenrant pages.

      I recommend trying WWW::Mechanize to attempt to automate testing of web applications.

      - Providing a skeleton module for making new tests will help people reuse code and send back to you too.

      Soon Data::FormValidator::Upload will be available and will serve as example of a plug-in module for Data::FormValidator.

      - Real world use may not be just a simple regex, business logic and ways to organize rules are more important (this is another whole ball 'o wax / module).

      The next version of Data::FormValidator (pretty much done, but not released yet), has better support for creating complex constraints requiring multiple inputs. This hasn't been stress-tested yet but seems like a good start here.

      - Even just a collection of validation subroutines which do not depend on each other and can be easily dropped in to one's code would be very helpful. Likewise, I have a lot of routines I've built up over various projects which I would have to drop in somewhere, e.g. email address validation, japanese phonetic conversions, local zipcode formats, double byte numbers, etc. So a way to add your own routines, and a set of tests for different data types to make sure they match, would also be good.

      Yes, and there are some other projects that are collections of reg-exs. It would be nice to integrate with them somehow if possible. These include CGI::Untaint and Regexp::Common. It would seem conceviable that someone could write a clever plug-in for D::FV that would use AUTOLOADing to transform regular expressions from one of these modules into the format that D::FV expects.

      - A homepage which lets people submit code (people can vote on it?) would be interesting.

      That could also be nice. You may be interested in joing the mailing list mentioned in teh documentation if you haven't already.

      -mark

        I have recently had a need to extend my CGI parameter validation and also presented a talk regarding my findings to a recent Birmingham Perl Mongers technical talk. While my research was incomplete and very much geared to what I wanted, it did highlight a few things.

        There are currently at least 6 modules that are primarily aimed at parameter validation:

        They all do parameter validation in different ways, although there are some crossovers, particularly regarding regex constraints. The first two were written for functional parameter validation, but can easily be used for CGI parameter validation.

        I personally found it difficult to understand why every single one had a different method of doing exactly the same thing. IMHO it would have been far better to have written plugins or subclasses to already existing modules. Each of the above have some great features that others don't, which makes it difficult for someone coming along afresh, to decided which one they want to use. Having plugins means you simply extend the ability to do another type of validation.

        Thus a single interface package, would be able to drag in <package>::RegEx, <package>::TypeCheck, <package>::Required, etc to handle specific rules of validation. This could also then tie into Regexp::Common for a list of standardised regex constaints.

        From my initial findings this is close to what CGI::Untaint is trying to do. However, the interface and error handling aren't what I would like. Data::FormValidator is better for that, although the interface to Params::Check I personally find easier to fit my mindset.

        Another bit of food for thought: some currently complain (sometimes even blowing a fuse) regards CGI.pm being all things to all men (or women), and that it should be paired down. I personally only use params() and header(). Something like CGI::FormBuilder sounds like it's trying to do that too. To my mind content presentation and input validation are two separate things and if I am to only use the validation portion, why would I want to install yet another set of content presentation routines that I'll never use?

        These have been my musing over the last few months and I have yet to come to any serious conclusions, so make of it what you will. However, I think it's going to be a while before I can finally decide on a single distribution to do the job.

        --
        Barbie | Birmingham Perl Mongers | http://birmingham.pm.org/

        Thank you very much Mark for your kind and detailed reply. Sorry I haven't had time to do more than a quick look but I will certainly study your module more and hope you enjoy doing it too.
Re: Data::FormValidator
by ozzy_cow (Initiate) on Jan 21, 2003 at 15:54 UTC
    imho Formbuilder module not only does validation (also with client side javascript), but also builds the forms for you, check out CGI::Formbuilder