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

I've used Template::Toolkit for a couple of years now, even done complicated things like filters, so a simple registration script that telescopes out as needed should be simple, right?

Apparently not. Please help.

First, the CGI:

#!/usr/bin/perl -w use strict; use warnings; use CGI qw/cgi-lib/; use Template; use Log::Log4perl; use Data::Dumper; our $logger; # Populate the order template. { # Start logging. Log::Log4perl::init('/var/www/perl/ontdist/order4.conf'); $logger = Log::Log4perl->get_logger('order4'); # Enter from a button push. my $cgi = CGI->new; my $vars = $cgi->Vars; $logger->debug("vars is ".Dumper($vars)); # Take data from form and put into AoH. my @reg_array; for ( 1..9 ) { my $last = "last_name$_"; my $first = "first_name$_"; if ( length($vars->{$last}) && length($vars->{$last}) ) { push ( @reg_array, { 'last_name' => $vars->{$last}, 'first_name' => $vars->{$first} } ); } else { # Leave a blank one at the end. push ( @reg_array, { 'last_name' => '', 'first_name' => '' } ); last; } } $logger->debug("reg_array is ".Dumper(\@reg_array)); # Put the AoH back into the vars hashref. $vars->{'reg_array'} = \@reg_array; $logger->debug("After adding 'reg_array' to vars, vars is ".Dumper +($vars)); # Output the resulting page. print $cgi->header; my $template = Template->new({}); $template->process('order4.tt2', $vars) or die "Unable to process order template: $!"; }

And then the template file:

<html> <body> <div align="center"> <form method="GET" action="order4.cgi"> <table border="1" cellpadding="10"> <tr> <td colspan="3"> <h3>Registrations</h3> <table border="1"> <tr> <th>Last name</th> <th>First name</th> </tr> [%- rc = 1 -%] [%- FOREACH reg IN reg_array -%] <tr> <td><input type="text" size="15" name="last_name[%- rc -%]" value="[%- last_name -%]"></td> <td><input type="text" size="15" name="first_name[%- rc -%]" value="[%- first_name -%]"></td> </tr> [%- rc = rc + 1 -%] [%- END -%] </table> </td> </tr> <tr> <td> <input type="submit" value="Recalculate" /> </td> </tr> </table> </form> </div> </body> </html>

I'm hoping that the reg_array AoH will fill up with first and last names from the form, but I can't seem to get the first set of names to come back from the initial form. Instead, Data::Dumper just tells that I have an array at $vars->{'reg_array'} (with a hex address, whoop-de-doo) but doesn't dump it for me. And the template doesn't seem to receive it.

2007-01-28 22:45:00,142 27851 [order4.cgi 48] DEBUG main: reg_array is + $VAR1 = [ { 'first_name' => 'Alex', 'last_name' => 'Beamish' }, { 'first_name' => '', 'last_name' => '' } ]; 2007-01-28 22:45:00,145 27851 [order4.cgi 53] DEBUG main: After adding + 'reg_array' to vars, vars is $VAR1 = { 'last_name1' => 'Beamish', 'first_name1' => 'Alex', 'reg_array' => 'ARRAY(0x839687c)' };

Why?

Alex / talexb / Toronto

"Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Replies are listed 'Best First'.
Re: Can't seem to use an AoH with Template::Toolkit
by perrin (Chancellor) on Jan 29, 2007 at 05:31 UTC
    In short, the problem is too much magic. When you call $cgi->Vars, you don't get a normal hashref. Instead, you get a ref to a tied hash, with different behavior from a normal hash. Try copying the params you want into a normal hash instead.
      When you call $cgi->Vars, you don't get a normal hashref.
      yes, in scalar context. in list context, you get a 'normal' hash.
      my %vars = $cgi->Vars;
        You mean array context list context, but yes, that does give you a list that you can make into your own normal hash. Here's the sub definition:
        sub Vars { my $q = shift; my %in; tie(%in,CGI,$q); return %in if wantarray; return \%in; }

      Maybe I've mis-understood you -- I made the code less fancy and used a hash instead of a hashref, as shown below, and got the sme result.

      for ( 1..9 ) { my $last = "last_name$_"; my $first = "first_name$_"; my %h; if ( length($vars->{$last}) && length($vars->{$last}) ) { $h{'last_name'} = $vars->{$last}; $h{'First_name'} = $vars->{$first}; } else { # Leave a blank one at the end. $h{'last_name'} = ''; $h{'First_name'} = ''; last; } push ( @reg_array, \%h ); }

      I guess I don't understand your answer.

      I'm able to get the information from $vars just fine, but it seems putting it back onto the form is a problem.

      Alex / talexb / Toronto

      "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

        In your original code, you get a hashref back from $cgi->Vars, and then you try to put @reg_array into it as if it were a normal hashref. That would work, except that $vars that comes back from $cgi->Vars is not a hashref, but rather a tied variable that CGI generated.

        I can't tell if the code you show here still has that problem because you didn't show that part. If it does, a quick fix would be to change that line where you call $cgi->Vars to this:

        my %vars = $cgi->Vars; my $vars = \%vars;