stonecolddevin has asked for the wisdom of the Perl Monks concerning the following question:
Hey gang,
I'm doing a website for my mom's puppy pillow company (http:.//www.boyosplace.com),
and I'm attempting to use HTML::Template and CGI::Application
to accomplish a shopping cart/store app.
What I'm running into is when I try to add the product to the cart, the item
parameter isn't being coerced (am i using the correct word in this case?) into the template paramater in the TMPL_LOOP from
the query string.
sub retrieve {
my $self = shift;
use Data::Dumper;
my $q = $self->query;
my $tmpl = $self->load_tmpl( "showitem.html",
loop_context_vars =>1,
associate => $q);
$tmpl->param( product => $self->dbh->selectall_arrayref(q[SELECT ima
+ge, price, description, serial FROM product WHERE id=?], { Slice => {
+} }, $q->param('item') ));
return $frm->build_page( { title => "Boyo's Place: " . $self->dbh->
+selectrow_array(q[SELECT name FROM product WHERE id=?], { Slice => {}
+ }, $q->param('item') ), output => $tmpl->output } ), $q->code(Dumper
+(\$tmpl));
}
<!--TMPL_LOOP name="product"-->
<table width="400" border="1" cellspacing="0" cellpadding="3">
<tr>
<td><!--TMPL_VAR name="image"--></td>
<td
align="right">Price: $<!--TMPL_VAR name="price"--></td>
</tr>
<tr>
<td
colspan="2"
align="justify"><!--TMPL_VAR name="description"--></td>
</tr>
<tr>
<td
colspan="2"><a href="?mode=add_to_cart&item=<!--TMPL_VAR n
+ame="item"-->&serialn=<!--TMPL_VAR name="serial"-->">add to cart<
+/a></td>
</tr>
</table>
<!--/TMPL_LOOP-->
I've tried using Data::Dumper to sort out the $tmpl hash...but to
no avail.
Can someone help me?
Re: CGI::Application/HTML::Template problem
by jeffa (Bishop) on Jan 12, 2006 at 15:26 UTC
|
How (Not) To Ask A Question: Only Post Relevant Code
Please break your problem down and ask again. You seem convinced that problem has to do with your usage of HTML::Template, so write a small throw-away script* that allows you pin point the problem easier. You might discover that the error does not involve HTML::Template, but instead CGI::App ... start small.
* People got tired of rewriting these throw away scripts they use to test code and starting writing Test Suites to keep them from pulling their hair out over debugging Big Balls of Mud, BTW. ;)
| [reply] [Watch: Dir/Any] |
|
Thanks very much jeffa...i've modified it to what i think is appropriate. what test suites would you recommend?
| [reply] [Watch: Dir/Any] |
|
use strict;
use warnings;
use HTML::Template;
use DBI;
my $id = shift || 42;
my $dbh = DBI->connect( ... );
my $tmpl = HTML::Template->new(filehandle => \*DATA);
my $product = $dbh->selectall_arrayref(q{
SELECT image, price, description, serial
FROM product
WHERE id = ?
}, {Slice => {}}, $id);
# i think it's better to use a variable instead of
# passing the results from the query directly to the
# $tmpl->param method (easier debugging)
$tmpl->param(product => $product);
print $tmpl->output;
__DATA__
<tmpl_loop product>
image: <tmpl_var image>
price: <tmpl_var price>
description: <tmpl_var description>
serial: <tmpl_var serial>
</tmpl_loop>
Look into the CPAN test suites for more about that. Test::More, Test::Simple, etc.
| [reply] [Watch: Dir/Any] [d/l] |
Re: CGI::Application/HTML::Template problem
by wfsp (Abbot) on Jan 12, 2006 at 16:51 UTC
|
Hi dhoss!
Taking a cue from jeffa.
Am I right in thinking that by "coerce" you mean using the HTML::Template "associate" option to use a parameter in the CGI query object?
If that is the case then perhaps the following may help.
#!/bin/perl5
use strict;
use warnings;
use CGI::Carp qw(
fatalsToBrowser
);
package main;
my $webapp = App->new();
$webapp->run();
package App;
use base 'CGI::Application';
use CGI;
sub cgiapp_get_query {
my $self = shift;
# initilise the query object
# with some params
my $q = CGI->new(
{
'test' => 'test page',
'greeting' => 'Hi there!',
}
);
return $q;
}
sub setup {
my $self = shift;
$self->start_mode('test');
$self->run_modes([qw|test|]);
}
sub test{
my $self = shift;
my $html;
{
local $/;
$html = <DATA>;
}
my $tmpl_obj = $self->load_tmpl(
\$html,
associate => $self->query,
);
return $tmpl_obj->output();
}
__DATA__
<html>
<head>
<title><!-- TMPL_VAR NAME = TEST --></title>
</head>
<body>
<p><!-- TMPL_VAR NAME = GREETING --></p>
</body>
</html>
output:
---------- Capture Output ----------
> "C:\Perl\bin\perl.exe" c_app.pl
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<title>test page</title>
</head>
<body>
<p>Hi there!</p>
</body>
</html>
> Terminated with exit code 0.
update:
dhoss! You changed your snippet while I preparing this post :-(
Hope this may still be of some use. :-)
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
that works, but i think it's the TMPL_LOOP that's giving me troubles...i think there's something in associating it with CGI (and yes i meant associate by coerce) that the TMPL_LOOP doesn't associate it's tags with CGI...
| [reply] [Watch: Dir/Any] |
|
I found your snippet a bit tricky to digest so I've blown some whitespace into it.
sub retrieve {
my $self = shift;
use Data::Dumper;
my $q = $self->query;
my $tmpl = $self->load_tmpl(
"showitem.html",
loop_context_vars =>1,
associate => $q
);
$tmpl->param(
product =>
$self->dbh->selectall_arrayref(
q[
SELECT
image,
price,
description,
serial
FROM
product
WHERE
id = ?
],
{ Slice => {} },
$q->param('item')
)
);
return $frm->build_page(
{ title => "Boyo's Place: " .
$self->dbh->selectrow_array(
q[
SELECT
name
FROM
product
WHERE
id=?
],
{ Slice => {} },
$q->param('item')
),
output => $tmpl->output
}
),
$q->code(Dumper(\$tmpl));
}
I would use a lot of temp vars to simplify the code and help establish what is happening.
e.g.
my $arrayref = $self->dbh->selectall_arrayref( etc....
die Dumper $arrayref;
# on a subsequent run
my $arrayref2 = $self->dbh->selectrow_array( etc...
die Dumper $arrayref2;
# and even
die Dumper $q->param('item');
You need to be sure you are feeding your template loop an array of hash refs. Each hash ref will need
item => $item_value
in it. You may have to loop through the dbh output yourself to put that in.
Hope that helps
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: CGI::Application/HTML::Template problem
by kutsu (Priest) on Jan 12, 2006 at 17:55 UTC
|
If you tryed to print "item" outside the template loop I bet it would print. This is because associate => $q is the same as doing $template->param(ITEM => $q->param('item')) for every param returned by cgi and TMPL_LOOPs introduce their own scope and can't use variables from outside the loop. If you set global_vars => 1 it should work.
Btw. in order to find I simplify your code by trying it without CGI::Application:
script:
#!/usr/bin/perl
use DBI;
use HTML::Template;
use CGI;
my $q = CGI->new();
my $dbh = DBI->connect('DBI:Pg:dbname=testdb', '', '');
$dbh->{RaiseError} = 1;
$aref = $dbh->selectall_arrayref( q/select foo, bar from test_table wh
+ere id = ?/, { Slice => {} }, $q->param('id') );
$dbh->disconnect;
my $template = HTML::Template->new(filename => 'test.tmpl', associate
+=> $q, global_vars => 1);
$template->param(TEST_LOOP => $aref);
print $template->output();
template:
id = <TMPL_VAR NAME=ID>
<!--remove global_vars and only this first ID will print-->
<TMPL_LOOP NAME=TEST_LOOP>
<p>
id: <TMPL_VAR NAME=ID> <br \>
foo: <TMPL_VAR NAME=FOO> <br \>
bar: <TMPL_VAR NAME=BAR>
</p>
</TMPL_LOOP>
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
global_vars was exactly what i was looking for...thanks so much kutsu, all!!!
| [reply] [Watch: Dir/Any] [d/l] |
Re: CGI::Application/HTML::Template problem
by markjugg (Curate) on Jan 12, 2006 at 19:06 UTC
|
To address the bigger picture issue, you may also be interested in Handel, an toolkit to help with shopping carts in Perl.
It integrates directly with other web frameworks, but can still be used from CGI::Application as well.
| [reply] [Watch: Dir/Any] |
Re: CGI::Application/HTML::Template problem
by jesuashok (Curate) on Jan 12, 2006 at 05:06 UTC
|
push @all_user_types, {
users_list => $values,
users => $values,
report_for_user => $values eq $c
+gi_user_type
};
$html->param(user_types => \@all_user_types );
<TMPL_LOOP NAME="user_types">
<option value="<TMPL_VAR NAME=users>" <TMPL_IF report_for_user>SEL
+ECTED</TMPL_IF>><TMPL_VAR NAME=users_list></option>
</TMPL_LOOP>
that is the way we used to Build the Elements Using TMPL_LOOP.
If that is Useful for you Please have a look.
"Keep pouring your ideas"
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
I'm not sure what this has to do with my code...did i miss something? I see no reference to my own code, nor any way to properly coerce the query string data into my template...
| [reply] [Watch: Dir/Any] |
|
You have
$tmpl->param( product => $self->dbh->selectall_arrayref(q[SELECT image, price, description, serial FROM product WHERE id=?], { Slice => {} }, $q->param('item') ));
You're selecting image, price, description and serial from the data, and those are going into the products loop as named elements, with their values as was selected.
The problem is, you're using $q->param('item') for your id, but since you're not including that as one of the values that will be available from the SQL, it isn't available for the product loop to use. CGI parameters are not automatically available to templates (though you can easily add them, though I forget the syntax off the top of my head... sorry it's 1am and I don't feel like looking it up).
Something like this will work as well
$tmpl->param( product => $self->dbh->selectall_arrayref(q[SELECT id as "item", image, price, description, serial FROM product WHERE id=?], { Slice => {} }, $q->param('item') ));
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] [d/l] |
|
|