Accessing array from Perl & DBI using Template Toolkit

--0003255760f61acdcb048d631ccc
Content-Type: text/plain; charset=ISO-8859-1

Hi, I'm trying to pickup CGI web application programming using Perl, DBI &
TT (Template Toolkit). This small application is about storing data (using
CGI::FormBuilder) list it using Template Toolkit. After retrieving records
from MySQL using DBI, I've problem understanding how to pass to Template
Toolkit, even though I've managed make it work by copy some code from Perl
Mongers & Template Toolkit's tutorial. Below are my codes :

>>> start of list.cgi <<<
#!/usr/bin/perl

use warnings;
use strict;
#use diagnostics;
use Template;
use DBI;

my %kar;
my $tt_file='list.tt';

my $tt = Template->new({
INCLUDE_PATH => './tt',
}) || die "$Template::ERROR\n";

my $vars = {
kars => \%kar,
};

sub db_select {
my ($dsn,$dbuser,$dbpass,$dbh,$plh_reg_no,$sth,$reg_no,$brand,$ cc);
$dsn = "dbi:mysql:database=mycars:hostname=127.0.0.1";
$dbuser = "driver";
$dbpass = "plaintext";
$dbh = DBI->connect($dsn,$dbuser,$dbpass)
or die "cannot connect to database : $DBI::errstr";

$plh_reg_no = "car%";
$sth = $dbh->prepare("SELECT reg_no,brand,CC FROM auto_details WHERE
reg_no like ?");
$sth->execute($plh_reg_no)
or die "Cannot execute statement : $DBI::errstr";

while (($reg_no, $brand, $cc) = $sth->fetchrow_array()) {
$kar{$reg_no} = {
reg_no => $reg_no,
brand => $brand,
cc => $cc
}
}
$dbh->disconnect();
}

db_select();

$tt->process($tt_file, $vars)
|| die "Template process failed: ", $tt->error(), "\n";
>>> end of list.cgi <<<

>>> start of list.tt <<<
Content-type: text/html


[% PROCESS header %]
Form <strong>List</strong>
<p>
<ul>
[% FOREACH kar IN kars.values %]
<li>[% kar.reg_no %], [% kar.brand %], [% kar.cc %]</li>
[% END %]
</ul>
</p>
[% PROCESS footer %]
>>> end of list.tt <<<

My question :
- I suppose the above code convert array into hash and pass it to TT, is
there any other way then this because I find that the line noise is a bit
too much.
- I've read about some where on some website that arrays passing to TT
should always use array reference ($sth->fetchrow_arrayref) instead of the
above, using arrays ($sth->fetchrow_array). If this were to use array
reference, can someone show some codes to me so that i may check it out and
try to understand.

Thanks in advance,
Edward.

--0003255760f61acdcb048d631ccc--
me [ Mo, 09 August 2010 14:25 ] [ ID #2045759 ]

Re: Accessing array from Perl & DBI using Template Toolkit

On 9 August 2010 13:25, me [at] <me [at] psybermonkey.net> wrote:
> Hi,

Hi,

Not sure why you had to send this twice.

I'm trying to pickup CGI web application programming using Perl, DBI &
....
....

>>>> start of list.tt <<<
> Content-type: text/html
>
>
> [% PROCESS header %]
> Form <strong>List</strong>
> <p>
> <ul>
> =A0 =A0[% FOREACH kar IN kars.values %]
> =A0 =A0<li>[% kar.reg_no %], [% kar.brand %], [% kar.cc %]</li>
> =A0 =A0[% END %]
> </ul>
> </p>
> [% PROCESS footer %]
>>>> end of list.tt <<<
>
> My question :
> - I suppose the above code convert array into hash and pass it to TT, is
> there any other way then this because I find that the line noise is a bit
> too much.

Line noise? What is it you want to cut out?

You are iterating over the values of your hash. You don't need to
specify values here, you could omit the values and, according to the
TT man page[1] do:

[% FOREACH kars %]
<li>[% reg_no %]....</li>
[% END %]


> - I've read about some where on some website that arrays passing to TT
> should always use array reference ($sth->fetchrow_arrayref) instead of th=
e
> above, using arrays ($sth->fetchrow_array). If this were to use array
> reference, can someone show some codes to me so that i may check it out a=
nd
> try to understand.

I think you might be getting a bit confused here. TT requires
references for it's parameters variable, so yes array, hash references
(or any reference that returns a list) but that is different from how
you retrieve data from the DBI. You turned that data into a hash of
hash references when you did this:

while (($reg_no, $brand, $cc) =3D $sth->fetchrow_array()) {
$kar{$reg_no} =3D {
reg_no =3D> $reg_no,
brand =3D> $brand,
cc =3D> $cc
}
}


If you want to use the DBI directly within TT then you should look at
using the TT DBI plugin[2]. you may get more help on TT matter from
the TT list[3].

Good luck,
Dp.


[1] http://template-toolkit.org/docs/manual/Directives.html#sect ion_FOREACH
[2] http://search.cpan.org/~rehsack/Template-DBI-2.65/lib/Templa te/DBI.pod
[3] http://mail.template-toolkit.org/mailman/listinfo/templates

--
To unsubscribe, e-mail: beginners-unsubscribe [at] perl.org
For additional commands, e-mail: beginners-help [at] perl.org
http://learn.perl.org/
dermot [ Di, 10 August 2010 10:49 ] [ ID #2045817 ]

Re: Accessing array from Perl & DBI using Template Toolkit

Hi Dermot,

On 10/08/10 4:49, Dermot wrote:
snip
> Hi,
>
> Not sure why you had to send this twice.
Oops, sorry about it, to everybody. The first email (my time shows 8pm
++) was sent but it didn't turn up in my email client (on this mailing
list, beginners [at] perl.org) and my hosting's webmail interface. After
waited for 2 hours, then I sent again the second email (10 pm ++) and
both turn up. I'm not sure why is it so.

snip
> Line noise? What is it you want to cut out?
>
> You are iterating over the values of your hash. You don't need to
> specify values here, you could omit the values and, according to the
> TT man page[1] do:
>
> [% FOREACH kars %]
>=A0=A0=A0 <li>[% reg_no %]....</li>
> [% END %]
>
I've tried this and it doesn't work. But I think I'm quite satisfy
with the current way of writing it as it kind of explain the hash
relationship.
e.g.
[% PROCESS header %]
Form <strong>List</strong>
<p>
<ul>
=A0=A0=A0 [% FOREACH kar IN kars.values %]
=A0=A0=A0 <li>[% kar.reg_no %], [% kar.brand %], [% kar.cc %]</li>
=A0=A0=A0 [% END %]
</ul>
</p>
[% PROCESS footer %]

snip
> I think you might be getting a bit confused here. TT requires
> references for it's parameters variable, so yes array, hash references
> (or any reference that returns a list) but that is different from how
> you retrieve data from the DBI. You turned that data into a hash of
> hash references when you did this:
>
You're absolutely correct about I'm confused. I can't differentiate
what's array & array references, hash & hash references. And I thought
all array are list.
At one point when I try to pass multiple row of array (query from DBI
using $sth->fetchrow_array) from perl to TT, it some how does not
work. Until I stumble on this working codes from Perl Mongers and turn
it into hash, then only it works. I was hoping someone over here can
show some codes on how to use $sth->fetchrow_arrayref to pass arrays
(or array references?) to TT.

snip
> If you want to use the DBI directly within TT then you should look at
> using the TT DBI plugin[2]. you may get more help on TT matter from
> the TT list[3].
>
Not going to use DBI within TT as my intention for TT is to solely
deal with design issue and keep the codes within CGI. Hopefully this
will isolate problems (if any) and ease my learning picking up web
programming. :)

> Good luck,
> Dp.
>
>
> [1] http://template-toolkit.org/docs/manual/Directives.html#sect ion_FOREA=
CH
> [2] http://search.cpan.org/~rehsack/Template-DBI-2.65/lib/Templa te/DBI.po=
d
> [3] http://mail.template-toolkit.org/mailman/listinfo/templates
>
I'll definitely check out the TT's mailing list.
Thanks for the explanation & help,
Edward.

--
To unsubscribe, e-mail: beginners-unsubscribe [at] perl.org
For additional commands, e-mail: beginners-help [at] perl.org
http://learn.perl.org/
myself [ Mi, 11 August 2010 06:15 ] [ ID #2045885 ]

Re: Accessing array from Perl & DBI using Template Toolkit

On 2010.08.11 00:15, MySelf rdtan.net wrote:

> On 10/08/10 4:49, Dermot wrote:

>> I think you might be getting a bit confused here. TT requires
>> references for it's parameters variable, so yes array, hash references
>> (or any reference that returns a list) but that is different from how
>> you retrieve data from the DBI. You turned that data into a hash of
>> hash references when you did this:
>>
> You're absolutely correct about I'm confused. I can't differentiate
> what's array & array references, hash & hash references.

Understanding references is imho one of the most important aspects of
being able to use Perl effectively, and minimize headache.

> At one point when I try to pass multiple row of array (query from DBI
> using $sth->fetchrow_array) from perl to TT, it some how does not
> work.

That's because iirc TT accepts a hashref as the data, and you must stuff
your arrayrefs within it.

Here is an example I've cobbled together quickly (using an email template):

my ( [at] notices, [at] renewals );

if ( $blah ) {
# push a new (anonymous) hash reference onto the array
push [at] notices, { username => $username, hours => $hours_balance, };
}
else {
push [at] renewals, { username => $username, hours => $hours_balance, };
}

# create a hash for the template data, and insert
# a reference to both of the arrays within it

my %tmpl_data;

$tmpl_data{ notices } = \ [at] notices;
$tmpl_data{ renewals } = \ [at] renewals;

my $msg = MIME::Lite::TT->new(

From => $from,
To => $to,
Subject => $subject,
Template => $tmpl,
TmplParams => \%tmpl_data, # create ref of hash
);

__END__

The data structure looks like this when printed with Dumper. It is a
hash reference that has two keys, who's values contain an array
reference. Each of the two array references point to an array that
contains a hash reference as each element. The data within these hrefs
are what are used in the foreach loops within the template itself.

Note that the below output contains two loops. I refer to this output
whenever I find myself having an issue generating output from within a
template loop:

acct-dev: ISP % sudo ./b.pl

$VAR1 = {
'renewals' => [
{
'hours' => '8.84 hours remaining',
'username' => 'xxx'
},
{
'hours' => '5.51 hours remaining',
'username' => 'xxx'
},
],
'notices' => [
{
'hours' => '13.17 hours remaining',
'username' => 'xxx'
},
{
'hours' => '10 hours remaining',
'username' => 'xxx'
},
]
};

__END__

The resulting template itself:

Clients sent Notices:

[% FOREACH item IN notices %]
[%item.username%]: [%item.hours%]
[% END %]

Clients sent Renewals:

[% FOREACH item IN renewals %]
[%item.username%]: [%item.hours%]
[% END %]

> Until I stumble on this working codes from Perl Mongers and turn
> it into hash, then only it works. I was hoping someone over here can
> show some codes on how to use $sth->fetchrow_arrayref to pass arrays
> (or array references?) to TT.

I believe what you want to do is fetch the data from the db as a hashref
instead, and push the rows into an array to generate your loop topology.
untested... I haven't used DBI in quite a long time:

my [at] loop_array;

push [at] loop_array, $sth->fetchrow_hashref();

my %top_level_tmpl_data;

$top_level_tmpl_data{ db_data } = \ [at] loop_array;

Then, you can either create an explicit reference to the top level hash
like this:

my $tmpl_data_ref = \%top_level_tmpl_data;

....or just skip that step and create the ref as you pass the data into TT.

I hope this is what you were after. Note that I prefer to use references
directly as opposed to creating array and hash first, but I thought that
it would be better in this case if I explicitly did things the long way.

Cheers,

Steve

--
To unsubscribe, e-mail: beginners-unsubscribe [at] perl.org
For additional commands, e-mail: beginners-help [at] perl.org
http://learn.perl.org/
Steve Bertrand [ Di, 10 August 2010 15:57 ] [ ID #2045893 ]

Re: Accessing array from Perl & DBI using Template Toolkit

Hi Steve,
> Understanding references is imho one of the most important aspects of
> being able to use Perl effectively, and minimize headache.
>

(stuffing my head into the Llama book)

> That's because iirc TT accepts a hashref as the data, and you must stuff
> your arrayrefs within it.
>
> Here is an example I've cobbled together quickly (using an email template):

snip

> I believe what you want to do is fetch the data from the db as a hashref
> instead, and push the rows into an array to generate your loop topology.
> untested... I haven't used DBI in quite a long time:
>
> my [at] loop_array;
>
> push [at] loop_array, $sth->fetchrow_hashref();
>
> my %top_level_tmpl_data;
>
> $top_level_tmpl_data{ db_data } = \ [at] loop_array;
>
> Then, you can either create an explicit reference to the top level hash
> like this:
>
> my $tmpl_data_ref = \%top_level_tmpl_data;
>
> ...or just skip that step and create the ref as you pass the data into TT.
>
> I hope this is what you were after. Note that I prefer to use references
> directly as opposed to creating array and hash first, but I thought that
> it would be better in this case if I explicitly did things the long way.
>

Hmm, this code look very much like what I want to do with it. I'll
definitely spend some time on it.

Thanks for the code examples & suggestion, this definitely shed some
light onto my question. Thanks!

Regards,
Edward.

--
To unsubscribe, e-mail: beginners-unsubscribe [at] perl.org
For additional commands, e-mail: beginners-help [at] perl.org
http://learn.perl.org/
myself [ Sa, 14 August 2010 17:30 ] [ ID #2046038 ]
Perl » gmane.comp.lang.perl.beginners » Accessing array from Perl & DBI using Template Toolkit

Vorheriges Thema: Regular expression question
Nächstes Thema: hash arrays