FormChecker - Perl Module for checking HTML form input

$Revision: 1.1 $


    use CGI::FormChecker;
    $fc = CGI::FormChecker->new;
    $fc->TemplateFile( '/path/to/template.html' );
    $errors_hash_ref = $fc->CheckInput( \@tests, @args );
    $output = $fc->ErrorHandler($errors_hash_ref);


FormChecker provides an interface for checking web-form input for problems. FormChecker is designed around the idea of applying a series of rules to the form input - any rules at all.

The idea is that in the real world the rules for form input are rather arbitray, for example some fields need to have only letters and number, other like a ``username'' must not already be in the database, whilst the ``state'' field must be one of the 50 US states only if the ``country'' is ``US'', and so forth.

FormChecker provides a uniform interface for performing a series of tests on user input, and if there are errors we can regenerate the form with per-rule error messages.

The error message for each occurance of a rule is controlled by the HTML coder - not the Perl coder (although default messages can be defined in the Perl code they are overriden by the HTML.)

The basic idea is that you define a series of tests and FormChecker performs each test, in the order given.

FormChecker provides methods to parse a template file (or string) and insert error messages for each of the failed tests. The text and location of the error messages is determined entirely inside the template, presumably by the HTML coder, not the Perl coder.

FormChecker uses the Text::TagTemplate module to handle the parsing and replacing of ERROR tags.


    my $fc = CGI::FormChecker->new;

Create a new FormChecker object.

    $fc->TemplateFile( '/path/to/template.html' );
    my $t = $fc->TemplateFile;

Set (or get) the file to use as a template.

Returns the current or new setting of TemplateFile;

To set the template to use, call TemplateFile with single argument which should be a path to the template file. It is best to use a full path if possible.

Dies with a stack trace if the template file is not found and readable, or if the path contains '..'.

The template file should contain one or more <#ERROR> tags each with 2 attributes:

    <#ERROR TEST="any_error" TEXT="At least 1 problem. See below...">
    <#ERROR TEST="require_email" TEXT="Email address required.">
    <#ERROR TEST="other_test" TEXT="&lt;li&gt;HTML message text">

Each occurance of an <#ERROR ...> tag will be replaced with either the error TEXT (if the test fails) or nothing (i.e. the whole tag will disappear) if the test is passed.

Note that the contents of the TEXT attribute must be HTML-encoded.

A given TEST can appear multiple times in the template, with different TEXT if you like.

    $fc->TemplateString( '<#ERROR TEST="testname" TEXT="There was an error here">' );
    my $t = $fc->TemplateFile;

Set (or get) a string to use as a template. This will override any template set with TemplateFile and the TemplateString will be used instead.

Returns the current or new setting of TemplateString.

Provided mainly for development and debugging purposes. Allows the programmer to specify a string to use as a template. Also useful if the template is to be generated by some other process, such as parsing one or more other templates to produce a new template.

To set the template to use, call TemplateString with a single argument which can be anything that evaluates to a string containing the <#ERROR ...> tag.

To un-set TemplateString (and allow the use of a TemplateFile) set TemplateString to an empty string: $fc->TemplateString( ``'' );

    my $errors_hash_ref = $fc->CheckInput( \@tests, @args );

This is the main method of FormChecker. CheckInput takes an array_ref of tests to perform (refs-to-subroutines) and an (optional) array or aguments.

Each test subroutine is called, in order, with the array of arguments (if any).

The return value of each test should be one of 2 things.

For success (test passed) the tests should return undef. For failure a test should return a hash-reference.

The keys should be unique test cases that will correspond to the TEST attribute of the tags in the template:

    <#ERROR TEST="testname" TEXT="blah blah">

The values of the hash-reference are the default TEXT to use for that error case. This default is overidden by the value of the TEXT attribute in the <#ERROR ..> tag.

Example of use:

    sub sample_test {
        my( $r, $arg2, $arg3 ) = @_;
        my %error;
        if ( $r->param('age') > $arg2 ) {
            $error{'age_check'} = 'Age check failed.';
            return \%error;
        return undef; 
    my $test = [
        sub { check_required( $r, \@Required) },
        sub { check_length( $r, 'firstname', $min, $max) },
        sub { check_length( $r, 'lastname', $min, $max) },

    my $errors_hash_ref = $fc->CheckInput($rules, $r, $arg2, $arg3);
    if ( %$$errors_hash_ref ) {
        # Uh oh. Found errors
        print $r->header;
        print $fc->ErrorHandler($errors_hash_ref);
        exit; # all done

In that example the first test to be called will be:

    sample_test($r, $arg2, $arg3);

The next 3 tests all ignore the arguments specified in

    CheckInput($rules, $r, $arg2, $arg3);

and supply their own arguments instead.

An example of a test that examines all the user-supplied parameters, looking for all the ones over 1000:

    sub sample_test2 {
        my( $r ) = @_; # ignore all but first argument
        my $target = 1000;
        my %error;
        foreach my $param ( $r->param ) {
            if ( $r->param("$param") > $target ) {
                $error{"${param}_too_large"} = "$param was too big.";
        return \%error if %error;
        return undef;
    my $output = $fc->ErrorHandler($errors_hash_ref);

ErrorHandler returns a string which is the HTML template with all the appropriate errors filled in.

The template to be parsed will be the current setting of TemplateFile, or TemplateString if set.

Takes a single argument: a hash-ref whose keys are the names of tests that failed, the values are the default message for that test. It is intended that the default message will be overidden by the HTML coder.

ErrorHandler looks for TagTemplate tags in the format:

    <#ERROR TEST="username_too_short" TEXT="Your Username is too short">
    <#ERROR TEST="username_missing" TEXT="&lt;li&gt;Please enter a login name.'>

Note that the contents of the TEXT attribute must be HTML-encoded.

If a key in the errors hash matches a TEST then the corresponding TEXT is used, otherwise the tag is simply removed (replaced with '').

Any other TagTemplate tags are left untouched.


Improve documentation
Add tests for make test that use a template file instead of a template string.
Add method(s) for warnings (non-fatal errors)


Matisse Enzer, <>




Copyright (c)2001 by Matisse Enzer

This package is free software and is provided ``as is'' without express or implied warranty. It may be used, redistributed and/or modified under the terms of the Perl Artistic License (see