Hagbone has asked for the wisdom of the Perl Monks concerning the following question:

I've recently been trying to come up to speed using Data::FormValidator. It's important to note that part of the challenge for me has to do with module familiarity ... while I feel I have a sound working knowledge of Perl in general, when it comes to understanding the nuances of sending and retrieving items to modules, I find myself struggling.

Case in point - I've set up a test form with 8 fields. The first four fields are required, and the last four fields are optional. When submitting the form, I'm intentionally leaving two of the four required fields blank - I'm trying to get FormValidator to spit back some sort of error message(s).

I'm able to have the script report the missing (and required) fields, but I can't seem to get any error message reports back from the module using the $results->(msgs) call. Here's the script code:

#!/usr/bin/perl use CGI qw(:standard); use strict; use Data::FormValidator; my $q = new CGI; my $profile = { required => [qw(one two three four)], optional => [qw(five six seven eight)], msgs =>{}, }; print "Content-type:text/html\n\n"; my %fdat = $q->Vars; my $results = Data::FormValidator->check(\%fdat, $profile); if ($results->has_missing) { foreach ($results->missing() ) { print "missing field name: $_ <br>"; } foreach ($results->msgs() ) { print "msgs output: $_ <br>"; } } exit;
And here's the HTML output:

missing field name: three
missing field name: two
msgs output: HASH(0x81ff9dc)

I've got this feeling that I'm missing something very fundamental here, but for the life of me, I can't figure it out. I've searched high and low for references to results->(msgs), and was unable to understand what little I found .... any help is appreciated.

Replies are listed 'Best First'.
Re: Retrieving "msgs" values from Data::FormValidator
by jdtoronto (Prior) on Dec 20, 2003 at 16:08 UTC
    Here is a D::FV that works.
    sub qs_process { my $self = shift; my $dbh = $self->param('mydbh'); my ($results, $err_page) = $self->check_rm('qs_display', { required => [qw/upfirstname uplastname upemail upusername uppa +ssword confirm_password/], optional => [qw/upzip upcountry/], filters => ['trim'], constraints => { uppassword => { #Make sure passwords are the same name => 'user_passwords', constraint => \&check_password, params => [qw(uppassword confirm_password)], }, upusername => { #Is username unique? name => 'user_username', constraint => sub { !$self->check_username(lc $_[0]); +} }, upemail => 'email', upzip => 'zip_or_postcode', }, msgs => { any_errors => 'err__', prefix => 'err_', constraints => { 'user_passwords' => "Your passwords don't match", 'user_username' => "Username not unique", }, }, } ); return $err_page if $err_page; # #Stuff here to handle case of validation being succesfull.
    Don't forget that your template must have a set of TMPL_VAR fields that match the error messages. This code is not functional as it has a couple of external validation functions you can't see.

    Here is a fragment of the template that is used for this form, note the 'err_' series of TMPL_VAR's in the third column.

    <form method="post" action="/app/app02.cgi"> <table border="0" cellpadding="0" cellspacing="2" width="490"> <tr> <td class="lbl" colspan="3"><font size="-1">Using this + form you can sign up for preview privileges on our system. You will +be able to see everything a full member would see, the only thing you + cannot do is actually make appointments.</font></td> </tr> <tr> <td class="lbl" width="160">First Name</td> <td class="value" width="230"><input type="text" name="upf +irstname" size="20"></td> <td class="err"><tmpl_var err_upfirstname></td> </tr> <tr> <td class="lbl" width="160">Last&nbsp;Name</td> <td class="value" width="230"><input type="text" name="upl +astname" size="20"></td> <td class="err"><tmpl_var err_uplastname></td> </tr>

    If you want to see it at work it is on a development server at: http://posiedon.mine.nu/app/app02.cgi?rm=mode_001

    jdtoronto PS I am on my out for about 8 hours, but msg me if you want some help and I can help later.

      As I mentioned, I'm severely challenged in the ways of modular thinking ... I just wish I understood how the code you offered is applied to the example I listed.

      Also - many of the forms I'd like to Validate with D::FV are static HTML pages ... and I'm assuming that D::FV can be used in these situations?

      I feel like I'm close to being able to use the module to check form input ... I can retrieve the missing fields, etc., but can't seem to get past retrieving a hash reference similar to:     HASH(0x81ff9dc)     for the     results->msgs()     info/data instead of real stuff. It's feeling like there's something fundamental that I'm just not recognizing .....

      Thanks for your suggestion, jdtoronto, ... maybe one of these months I'll start to understand the concepts more clearly.

Re: Retrieving "msgs" values from Data::FormValidator
by cees (Curate) on Dec 20, 2003 at 17:42 UTC

    Whenever you print out a variable and you see something like 'HASH(0x81ff9dc)', then what perl is telling you is that your variable holds a reference to a hash (the hex number is the memory location of the hash). The best thing to do at this stage, if you don't know what is in the hash, is to use Data::Dumper to dump the contents of the hash into a human readable format.

    use Data::Dumper; print Data::Dumper::Dumper($results->msgs());

    I haven't used the msgs method of D::FV, so I don't know what the format of the HASHes will be. But you will get a good idea after Dumping out its structure.

    If you have more questions about accessing the data after you have viewed this, come back and ask again. But this should at least get you further on the way to solving the problem yourself.

    Good Luck

    - Cees

Re: Retrieving "msgs" values from Data::FormValidator
by Hagbone (Monk) on Dec 20, 2003 at 20:08 UTC
    Thanks Cees ... I believe I'm getting closer to understanding this .... I used Data::Dumper as suggested, and the output was:
    $VAR1 = { 'three' => '<span style="color:red;font-weight:bold"><span i +d="dfv_errors">* Missing</span></span>', 'two' => '<span style="color:red;font-weight:bold"><span id= +"dfv_errors">* Missing</span></span>' };
    This appears to be the default outpur from D::FV. ... it seems the problem I'm having is not knowing how to call the elements from the hash above.

    It appears that the keys of the hash are the field names of the required fields that were submitted as blanks from the form.

    And it also appears that I should be able to call the items from the above hash and associate them to the $results->(missing) array .... that is if I knew how to call the hash value ...

    It looks to these rookie eyes that Data::Dumper shows the hash name as "$VAR1" ... and I'm guessing that in order for me to call the hash values, I need to know the hash name ???

    I've been trying all kinds of combinations:

    print $results->msgs(); print $results->msgs(you name it); print $results->msgs(I've tried it);
    but I still keep getting a damn hash reference, and no data. Frustrating, to say the least ;)

      I'm glad to see that you are on the right track. What you need to learn now is how to deal with references and data structures in perl. I would recommend that you read the references tutorial here on PerlMonks to get you familiar with how to access data structures in perl.

      Now, back to D::FV. From the docs it says that the msgs method returns a hash reference. So in order to access the data you will need to know how to de-reference that hash. The folowing code should be able to print out your messages:

      my $messages = $results->msgs(); # $messages now contains a hashref # The arrow operator de-references the hashref print "input two: ", $messages->{two}, $/; print "input three: ", $messages->{three}, $/; # Or de-reference it first and then print my %messages_hash = %$messages; print "input two: ", $messages_hash{two}, $/; print "input three: ", $messages_hash{three}, $/; # Or print out everything in messages while (my($key, $value) = each %$messages) { print "input $key: $value$/"; }

      I have not tested the above code, but if msgs does return a hash reference then it should work.

      Hope this helps...

      - Cees

        my $messages = $results->msgs(); # $messages now contains a hashref
        I guess that's where my brain cramp was .... following your example allowed me to access the values - thanks very much.

        I think the trouble I'm having coming up to speed is wrapping my brain around the various forms of data ... for some reason, items such as %$message are still un-intuitive for me.

        >I would recommend that you read the references tutorial here on PerlMonks to get you familiar with how to access data structures in perl.

        I certainly will (probably numerous times) ... sometimes it's difficult to know what to read when you don't know what you need ;).

        I've got a feeling that when it finally becomes clear, it will be in a threshold way, and I'll find myself wondering why it took me so long to grasp it.