in reply to Re: Best way to send records to the browser?
in thread Best way to send records to the browser?

Thanks for the help.

I'm really trying to keep my code out of my templates. In fact, that is why I opted to use TT2 in the first place. I have a web designer working on this project who doesn't understand TT2 or Perl.

It appears that other template tools (like Template::HTML) allow you to pass arrays to templates. I have written code code that basically builds an array of hashes. Its fairly compact. This would work for Template::HTML, but not for TT2.

I think I have to create a hash of hashes. Unfortunately, I'm not sure how to do this syntactically - and this is where I could use a little help.

Am I heading down the right path? My thought is to create a hash for each relevant record in the table. Then, I can create a hash of hashes to encompass all of the records. However, if I send the HoH to TT2, will it understand it? This is uncharted territory for me. Also, I'm not sure how the syntax works for building a HoH in Perl. I'm still researching this, but haven't figured it out (help appreciated).

I guess the other thing I could do is take my existing array of hashes and parse it with Perl to build one large hash. I'm sure this would work (I've done something similar in the past) but one would think there exists an easier (preferred) way to do all of this. Hence my post here for the Monks.

I really appreciate any further guidance you experts can offer me.

:-)
  • Comment on Re^2: Best way to send records to the browser?

Replies are listed 'Best First'.
Re^3: Best way to send records to the browser?
by Your Mother (Archbishop) on Jun 26, 2010 at 16:17 UTC

    This would work for Template::HTML, but not for TT2.

    Of course it would. You can pass arbitrary perl data structures to TT and its loop controls are better/deeper than HTML::Template's. The reason some people prefer HT over TT is precisely because it has drastically fewer features (and better speed but for the template layer, that's generally the dumbest place to try to optimize) so it is closer to the purist idea of a view; which, as you mention, can be better for the designer, etc. There is nothing HT does that you can't do in TT.

    Why don't you post some sample code of what your data structure looks like?

      Didn't mean to make it sounds like I'm an advocate for HT over TT2. I recognize the power TT2 provides, and I like what you can do with it. Just wish you could pass it arrays directly from Perl.

      My MySQL query looks like this:

      # issue query my $sth = $dbh -> prepare("SELECT uid, fname, lname FROM users") || &b +ail_out("Error: cannot prepare DB query"); $sth -> execute() || &bail_out("Error: cannot execute DB query");

      The following loop yields an array with all relevant keys and values as individual elements. The results are printed to the terminal for testing:

      while (@rray = $sth -> fetchrow_array) { $row{uid} = $rray[0]; $row{fname} = $rray[1]; $row{lname} = $rray[2]; push @rows, %row; } foreach (@rows) { print "$_\n"; }

      This next variation is an attempt to build a hash instead of an array. It only builds one column (lname) from the table at this time. Keys are defined as records.

      while (@rray = $sth -> fetchrow_array) { $record = "record_$i"; $hash{$record} = $rray[1]; $i += 1; } my ($key, $value); while (($key, $value) = each(%hash)) { print "key = $key, value = $value\n"; }

      The two pieces of code above work. Finally, however, my attempt to build a HoH is failing. Here is what I have so far:

      while (@rray = $sth -> fetchrow_array) { $record = "record_$i"; $hash1{fname} = $rray[1]; $hash2{$record} = %hash1; $i += 1; } while (($key, $value) = each(%hash2)) { print $hash2{$value} -> {fname}; }

      There are obviously some problems here. Can you offer me some guidance?

      Thanks!

        $hash1{fname} = $rray[1]; $hash2{$record} = %hash1;

        Values stored in hash entries can only be scalar (not hashes or arrays), so you need to store a reference to a hash, which is scalar.  You get a reference with \

        $hash2{$record} = \%hash1;

        But note that this would store references to the same global hash, in which you'd just overwrite the fname entry for every record.  You most likely want separate hashes, i.e.

        my %hash1; # new hash instance $hash1{fname} = $rray[1]; $hash2{$record} = \%hash1;

        or simply

        $hash2{$record} = { fname => $rray[1] };

        (the { } create an anonymous hash and return a reference to it)

        Here you go. This should be close to what you're doing (adjust the column names in the query). Related reading of interest: DBI recipes.

        use warnings; use strict; use Template; use DBI; my $dbh = DBI->connect("dbi:mysql:mycow;mysql_read_default_file=$ENV{H +OME}/.my.cnf", undef, undef, { RaiseError => 1 }); my $sth = $dbh->prepare("SELECT id, name, email FROM user LIMIT 3 OFFS +ET 100"); $sth->execute(); my $employees_loh = $sth->fetchall_arrayref({}); my $tt = Template->new(); $tt->process(\*DATA, { users => $employees_loh }) or die $tt->error(), "\n"; __END__ [% FOR user IN users %] <div class="record"> <div class="id">[% user.id %]</div> <div class="name">[% user.name %]</div> <div class="email">[% user.email %]</div> </div> [% END %] -- Output ------------------ <div class="record"> <div class="id">101</div> <div class="name">Actaeonis</div> <div class="email">Accius@sitesviagra.com</div> </div> <div class="record"> <div class="id">102</div> <div class="name">varvang</div> <div class="email">vartang@roliks.com</div> </div> <div class="record"> <div class="id">103</div> <div class="name">JacobHorony</div> <div class="email">jeremilerom@bestbussiness.net</div> </div>

        I wasn't trying to disrespect HTML::Template too! It's a fine choice and I understand why some prefer a view without a mini-language on top.