Thread: [htmltmpl] (newbie) How to populate an array of hash references one by one?
Brought to you by:
samtregar
From: Ken C. <ke...@ke...> - 2003-11-24 19:47:38
|
Hi All, I'm playing with HTML::Template, and I've run into something that should be easy, but I don't see how it can work. The docs say to pass many elements for a loop, you do this: $template->param( loopvar => [ { name=>"foo",value=>"baloney" }, { name=>"bar",value=>"tiple" }, { name=>"blah",value=>"mulroney" }, ], ); So, I'm using anonymous array and hash operators to make an anonymous array of hash references. (page 246, "The anonymous array composer", camel book). That's great, but what if you don't know your content at programming time? {Just for context, I'm using perl 5.6.1, HTML::Template 2.6, with "use strict"}. Ideally, I want to add a line at a time to that array, and then pass that whole array to the param. So, I tried various things: # attempt 1 my @test = (); push @test { name=>"foo",value=>"blitz" }; # Gets "Global symbol "%test" requires explicit package name at ...[push line]" !?!?! there is no %test. # attempt 2 my @test = (); push @test \{ name=>"foo",value=>"blitz" }; # Gets "Backslash found where operator expected at ...[push line]" # attempt 3 my @test = (); push @test [ { name=>"foo",value=>"blitz" } ]; # Gets "Type of arg 1 to push must be array (not array slice) at ...[push line]" [more stuff along the same lines that didn't work...] *grrr* Okay, says I, I'll work on something else and wait for the muse to strike. I decide I'll figure out how to pass an array into a param... # attempt 4 my @test = [ { a=>"b",c=>"d" }, { e=>"f",g=>"h" }, ]; $template->param(itemloop => \@test); # Gets "HTML::Template->output() : fatal error in loop output : HTML::Template->param() : Single reference arg to param() must be a has-ref! You gave me a ARRAY. at ..." # attempt 5 my %test; $test{"a"}="b"; $test{"c"}="d"; $test{"e"}="f"; $template->param(itemloop => \%test); # Gets "HTML::Template::param() : attempt to set parameter 'itemloop' with a scalar - parameter is not a TMPL_VAR! at ..." # attempt 6 my %test; $test{"a"}="b"; $test{"c"}="d"; $test{"e"}="f"; $template->param(itemloop => %test); # Gets "You gave me an odd number of parameters to param()! at ..." Ach. So, no better luck. Clearly there's some simple skullduggery I'm missing here. Can anyone enlighten me? Pointers to documentation would be fine, though the HTML::Template page and the perldoc for HTML::Template didn't help too much already. -Ken |
From: Timm M. <tm...@ag...> - 2003-11-24 20:03:37
|
><> ># attempt 1 >my @test = (); >push @test { name=>"foo",value=>"blitz" }; ># Gets "Global symbol "%test" requires explicit package name at ...[push >line]" !?!?! there is no %test. You forgot a comma, so Perl interpreted it as something like this: push @test{'name','foo',value','blitz'}; Adding a comma after @test will make it work ># attempt 2 >my @test = (); >push @test \{ name=>"foo",value=>"blitz" }; ># Gets "Backslash found where operator expected at ...[push line]" This would have made a reference to a hash reference (if you had the comma in), which wouldn't have worked anyway. ><> ># attempt 4 >my @test = [ > { a=>"b",c=>"d" }, > { e=>"f",g=>"h" }, >]; >$template->param(itemloop => \@test); ># Gets "HTML::Template->output() : fatal error in loop output : >HTML::Template->param() : Single reference arg to param() must be a >has-ref! You gave me a ARRAY. at ..." To Perl, you're creating an array, the first element being an arrayref, which contains hashrefs. What you actually wanted to do is: my @test = ( { a=>"b",c=>"d" }, { e=>"f",g=>"h" }, ); Note parens instead of square brackets. ># attempt 5 >my %test; >$test{"a"}="b"; >$test{"c"}="d"; >$test{"e"}="f"; >$template->param(itemloop => \%test); ># Gets "HTML::Template::param() : attempt to set parameter 'itemloop' >with a scalar - parameter is not a TMPL_VAR! at ..." This one is interesting. Looks like HTML::Template trys to use the hashref in its scalar representation (like HASH(0xffffffff)) and then errors out when your param isn't a loop. ># attempt 6 >my %test; >$test{"a"}="b"; >$test{"c"}="d"; >$test{"e"}="f"; >$template->param(itemloop => %test); ># Gets "You gave me an odd number of parameters to param()! at ..." To Perl, your params are being flatened like this: $template->param(itemloop => a, b => 'c', d => 'e', f ); That's because the param method takes a list with all the parameters being flattened into a hash. Since you're putting 'itemloop => ' first, Perl sees that as the first element in the hash. That's why you need to use references. Please read perldsc. <> |
From: Jayson P. <JP...@je...> - 2003-11-24 20:05:38
|
Attempt #1-3 are missing a comma between your array and your list. Solution, use a comma. Attempt #4 is assigning an array reference as the first element of an array and then you are using a reference to that array. Solution, use () instead of [] in your assignment. Attempt #5 is a hashref not an array ref. Solution, put all your hash elements into an array. Attempt #6 is a hash itself, not even an array. I'd recommend using #1 with a comma like so (push @test, { name=3D>"foo",value=3D>"blitz" };) and you should be working. --Jayson Ken Corey <ke...@ke...> Sent by: htm...@li... 11/24/03 02:55 PM To: htm...@li... cc: Subject: [htmltmpl] (newbie) How to populate an array of hash references one by one=3F Hi All, I'm playing with HTML::Template, and I've run into something that should be easy, but I don't see how it can work. The docs say to pass many elements for a loop, you do this: $template->param( loopvar =3D> [ { name=3D>"foo",value=3D>"baloney" }, { name=3D>"bar",value=3D>"tiple" }, { name=3D>"blah",value=3D>"mulroney" }, ], ); So, I'm using anonymous array and hash operators to make an anonymous array of hash references. (page 246, "The anonymous array composer", camel book). That's great, but what if you don't know your content at programming time=3F {Just for context, I'm using perl 5.6.1, HTML::Template 2.6, with "use strict"}. Ideally, I want to add a line at a time to that array, and then pass that whole array to the param. So, I tried various things: # attempt 1 my @test =3D (); push @test { name=3D>"foo",value=3D>"blitz" }; # Gets "Global symbol "%test" requires explicit package name at ...[push line]" !=3F!=3F! there is no %test. # attempt 2 my @test =3D (); push @test \{ name=3D>"foo",value=3D>"blitz" }; # Gets "Backslash found where operator expected at ...[push line]" # attempt 3 my @test =3D (); push @test [ { name=3D>"foo",value=3D>"blitz" } ]; # Gets "Type of arg 1 to push must be array (not array slice) at ...[push line]" [more stuff along the same lines that didn't work...] *grrr* Okay, says I, I'll work on something else and wait for the muse to strike. I decide I'll figure out how to pass an array into a param... # attempt 4 my @test =3D [ { a=3D>"b",c=3D>"d" }, { e=3D>"f",g=3D>"h" }, ]; $template->param(itemloop =3D> \@test); # Gets "HTML::Template->output() : fatal error in loop output : HTML::Template->param() : Single reference arg to param() must be a has-ref! You gave me a ARRAY. at ..." # attempt 5 my %test; $test{"a"}=3D"b"; $test{"c"}=3D"d"; $test{"e"}=3D"f"; $template->param(itemloop =3D> \%test); # Gets "HTML::Template::param() : attempt to set parameter 'itemloop' with a scalar - parameter is not a TMPL=5FVAR! at ..." # attempt 6 my %test; $test{"a"}=3D"b"; $test{"c"}=3D"d"; $test{"e"}=3D"f"; $template->param(itemloop =3D> %test); # Gets "You gave me an odd number of parameters to param()! at ..." Ach. So, no better luck. Clearly there's some simple skullduggery I'm missing here. Can anyone enlighten me=3F Pointers to documentation would be fine, though the HTML::Template page and the perldoc for HTML::Template didn't help too much already. -Ken ------------------------------------------------------- This SF.net email is sponsored by: SF.net Giveback Program. Does SourceForge.net help you be more productive=3F Does it help you create better code=3F SHARE THE LOVE, and help us help YOU! Click Here: http://sourceforge.net/donate/ =5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F= =5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F Html-template-users mailing list Htm...@li... https://lists.sourceforge.net/lists/listinfo/html-template-users Jefferies archives and reviews outgoing and incoming e-mail. It may be prod= uced at the request of regulators or in connection with civil litigation. Jefferies accepts no liability for any errors or omissions arising as a resu= lt of transmission. Use by other than intended recipients is prohibited. |
From: Puneet K. <pk...@ei...> - 2003-11-24 20:14:38
|
Ken Corey wrote: > Hi All, > > I'm playing with HTML::Template, and I've run into something that should > be easy, but I don't see how it can work. > > The docs say to pass many elements for a loop, you do this: > > $template->param( loopvar => [ > { name=>"foo",value=>"baloney" }, > { name=>"bar",value=>"tiple" }, > { name=>"blah",value=>"mulroney" }, > ], > ); > > So, I'm using anonymous array and hash operators to make an anonymous > array of hash references. (page 246, "The anonymous array composer", > camel book). > > That's great, but what if you don't know your content at programming > time? This comes up frequently. Maybe the explanation(s) should be added to the H::T docs (htdocs!) Apologies if you already know some of the following. A 2-d table (columns x rows) is a common, dareisay, the only representation of a database table. That is how you will also (in all likelihood) display it on your html page. So, imagine that each row is a hash where each key is the fieldname, and the value is the value of that field for that row. Now, if you string up a bunch of such hashes in a list, you get an array of hashes. Of course, since an array can store only scalara, it is actually an array of refs to hashes. And, since the $template->param is nothing but a hash itself, and since value of a key in a hash is also a scalar, a ref to our array of refs to hashes is applied. So, you have $template->param('result' => $arrayref); where arrayref is a ref to our array of refs to hashes. If you are using DBI (which is what you would typically, to grab the data from a table), things get extremely easy. The $sth->fetchall_arrayref({}) conveniently fetches a ref to an array of refs to hashes... cool. so, $template->param('result' => $sth->fetchall_arrayref({})); works groovy. You can construct this programmatically if you are reading sequentially from a file. my @result; while (<FILE>) { my %row; .. .. do something to split the row and stuff it into %row .. .. push(@result, \%row); } $template->param('result' => \@result); The main problem is if you don't know the names of the fields you are pulling from a table (such as you would if you were to SELECT * FROM table). Since the fieldnames become the hash keynames, you would not be able to display them in your html page, because you wouldn't know what you pulled. To get around this, you simply treat each row as an array of hashes where each hash contains only one key called 'field' (or whatever), and its value is the value of that field. So you end up with an array of hashes where each hash is an array of hashes where each hash is a single field and its value. Cool. Please always use strict and -w. Hth. |
From: Ken C. <ke...@ke...> - 2003-11-25 07:10:19
|
On Mon, 2003-11-24 at 20:19, Puneet Kishor wrote: > This comes up frequently. Maybe the explanation(s) should be added to > the H::T docs (htdocs!) Might be a good idea! > $template->param('result' => $sth->fetchall_arrayref({})); Thanks for pointing this out, the '({})' to arrayref would have thrown me for a loop...uh...no pun intended. > You can construct this programmatically if you are reading sequentially > from a file. Thanks, this info allowed me to get it working in less than 30 seconds. Yay! I /knew/ it was something simple. > Please always use strict and -w. The first two lines of my cgi script are: #!/usr/bin/perl -w use strict; When you say to "use -w", is that sufficient? What about if it's being run under mod_perl and Apache::Registry so that line isn't, as I understand it, being invoked. Does the perl still check to see if there are invocation flags on the first line and respect them? Hrm... -Ken |
From: Puneet K. <pk...@ei...> - 2003-11-25 07:26:24
|
On Nov 25, 2003, at 1:18 AM, Ken Corey wrote: > On Mon, 2003-11-24 at 20:19, Puneet Kishor wrote: >> This comes up frequently. Maybe the explanation(s) should be added to >> the H::T docs (htdocs!) > > Might be a good idea! yeah... maybe Sam T might consider adding something like what I wrote up... something that directly ties using DBI with H::T, because inevitably someone will want to use MySQL or some such. > >> $template->param('result' => $sth->fetchall_arrayref({})); > > Thanks for pointing this out, the '({})' to arrayref would have thrown > me for a loop...uh...no pun intended. > >> You can construct this programmatically if you are reading >> sequentially >> from a file. > > Thanks, this info allowed me to get it working in less than 30 seconds. > Yay! I /knew/ it was something simple. > >> Please always use strict and -w. > > The first two lines of my cgi script are: > > #!/usr/bin/perl -w > use strict; > > When you say to "use -w", is that sufficient? well, no... I really meant what you already have #/usr/bin/perl -w use strict; you can also "use diagnostics" or splain if you really want a chatty system. > What about if it's being > run under mod_perl and Apache::Registry so that line isn't, as I > understand it, being invoked. Does the perl still check to see if > there > are invocation flags on the first line and respect them? > dunno. I don't use mod_perl or A::R. I am cc-ing this to the list (as you should do also) because someone else would likely have the answer to this (and other questions). |
From: Andrew B. <an...@br...> - 2003-11-25 13:11:40
|
On 11/25/03 at 1:24 AM, pk...@ei... (Puneet Kishor) wrote: > > On Nov 25, 2003, at 1:18 AM, Ken Corey wrote: > > So, I'm using anonymous array and hash operators to make an anonymous > array of hash references. (page 246, "The anonymous array composer", > camel book). > > That's great, but what if you don't know your content at programming > time? > > > On Mon, 2003-11-24 at 20:19, Puneet Kishor wrote: > >> This comes up frequently. Maybe the explanation(s) should be added > >> to the H::T docs (htdocs!) > > > > Might be a good idea! > > yeah... maybe Sam T might consider adding something like what I wrote > up... something that directly ties using DBI with H::T, because > inevitably someone will want to use MySQL or some such. > Seems to me that it's a question of using Perl data structures and references, not really an H::T question. The H::T documentation is already far superior to many modules out there. You need to draw the line somewhere. Whatever. Andrew |
From: Timm M. <tm...@ag...> - 2003-11-25 14:00:11
|
>><> >>The first two lines of my cgi script are: >> >>#!/usr/bin/perl -w >>use strict; >> >>When you say to "use -w", is that sufficient? > >well, no... I really meant what you already have > >#/usr/bin/perl -w >use strict; > >you can also "use diagnostics" or splain if you really want a chatty system. > >> What about if it's being >>run under mod_perl and Apache::Registry so that line isn't, as I >>understand it, being invoked. Does the perl still check to see if there >>are invocation flags on the first line and respect them? > >dunno. I don't use mod_perl or A::R. I am cc-ing this to the list (as you >should do also) because someone else would likely have the answer to this >(and other questions). You can put a 'use warnings;' instead of using -w. There are also places in the mod_perl config where you can modify what switches perl is invoked with. 'use warnings' has the advantage that it can be lexically scoped, so you can shut off warnings you know are harmless for a block. |