Hi Lai,
I'm trying on my own to figure out the array bit. I have no idea if I'm on the right track.
I modified my query section in the shop_parameters subroutine which I included in my original node.
Can you look at this code and tell me if I'm on the right track?
Here's the code...
$sth = $dbh->prepare ("SELECT * FROM catalog_pet, item $where ORDER BY
+ catalog_pet.product_id $limit");
my @colors =();
while (my $ref = $sth->fetchrow_hashref())
{
my %color = (
'item_id' => $ref->{'item_id'},
'color' => $ref->{'color'}
);
push @{$colors{$ref->{'item_id'}}}, \%color;
}
$sth->execute (@placeholder);
$page = get_product_table ($sth);
Thanks. | [reply] [d/l] |
Good Morning Lai,
I've read through your doc and I'm starting to see what is happening.
I did a few things with my code to accomodate your code.
First, originally in my shop_parameters subroutine, I was doing a join between my two tables. I removed that join since we're creating another query that is extracting the colors into the array. Am I correct in doing that?
Second, I modified my code that produces the results into a table. When I run the script, I'm receiving the following message:
Can't call method "prepare" on an undefined value
I've pasted the code for the table with the results. I think I defined everything that needed to be defined. But, I'm not sure. Also, in your doc, you mentioned something about RTFM. What does that mean? Can you view the modified code again and spot check why I'm receiving that error message?
sub get_product_table
{
my $sth = shift;
my ($dbh, $clref) = @_;
my @row;
my @nav_link;
my ($color, @color);
while (my $ref = $sth->fetchrow_hashref ())
{
$clref = $dbh->prepare ("SELECT color FROM item WHERE p
+rod_id = ".$ref->{product_id});
$clref->execute();
while (my $color = $clref->fetchrow_hashref()) {
push @{$ref->{color}}, $color->{color};
}
my $serve_url = sprintf ("serve_image.cgi?product_id=%s;picture",
+ escape ($ref->{product_id}));
# generate a form allowing a quantity of the item to be added
# to the cart
push (@row, start_form(-method=>'POST', -action=>url()),
hidden( -name => "choice", -override => 1,
-default => "add" ),
hidden( -name => "product_id", -override => 1,
-default => escapeHTML($ref->{product_id})),
Tr ({-style=>"font-family: verdana; font-size: 10pt;"},
td (img ({-src => $serve_url, -alt => escapeHTML($ref->{product_id}
+)})),
td ({-width=>"80", -valign=>"top", -align => "center"}, escapeHTML(
+ $ref->{product_id} )),
td ({-width=>"190", -valign=>"top"}, escapeHTML( $ref->{description
+} ))),
td (" "),
Tr ({-style=>"font-family: verdana; font-size: 10pt;"},
td ({-colspan => "3", -align => "right", -style=>"font-weight: 700;
+ color:blue;"}, "Price: \$", escapeHTML( sprintf( "%.2f", $ref->{pri
+ce}))),
Tr ({-style=>"font-family: verdana; font-size: 10pt;"},
td ({-colspan => "3", -align => "right"}, "Colors:", popup_menu( -n
+ame => "color", -values => $ref->{color}))),
Tr ({-style=>"font-family: verdana; font-size: 10pt;"},
td ({-colspan => "3", -align => "right"}, "Quantity:", popup_menu(
+-name => "quantity", -values => ["1", "2", "3", "4", "5", "6", "7", "
+8", "9"])),
td (image_button( -name => "Add Item", -src=>"../images/add.jpg", -
+border=>"0" )))),
Tr ({-valign=>"top"},
td ({-colspan=>"7", -width=>"100%"}, hr)),
end_form()
);
}
$sth->finish ();
return undef unless @row; # no items?
return (table ({-border => 0, -align => "center", -style=>"font-fa
+mily: verdana; font-size: 10pt;"}, @row));
}
Thanks again for your help.
Oh, do you have any good recommendations for books that I can buy to learn more about Perl? There's so many of them out there, I don't know what's good or not.
Have a good day. | [reply] [d/l] |
Good Afternoon Lai,
Please disregard my previous, Good Morning, post. I solved my error problem. Plus, when I run the script, the popup menu appears as it should.
Now, I need to go one step further. Let's say you want to buy two blankets, the same exact blanket, one will be in blue and the other in green.
When I add an item with one color and then try to add the same item with another color, the first item/color is removed.
Right now, my Add routine is using product_id which is a higher level product code. In the same table that contains the color field, I have a prod_id which is a unique key for each item for each color. For example, green blanket is 7GR, blue blanket is 7BL, etc. It's the prod_id that is in with the color table that needs to be passed to my add_item subroutine as a $ref->prod_id.
I made an attempt to modify the color array code to include this prod_id. Unfortunately, when I run the script, I'm receiving and Internal Server Error. Apparently, it does not like something that I did.
Can you spot check my code to see if I'm bringing in the prod_id with the color correctly?
sub get_product_table
{
my $sth = shift;
my $dbh = WebDB::connect ();
my ($clref, $ref);
my @row;
my @nav_link;
my ($color, @color);
while (my $ref = $sth->fetchrow_hashref ())
{
$clref = $dbh->prepare ("SELECT color, prod_id FROM ite
+m WHERE prod_id = ".$ref->{product_id});
$clref->execute();
while (my ($color, $prod_id) = $clref->fetchrow_hashref
+()) {
push @{$ref->{color}, $ref->{prod_id}}, ($color->{color
+}, $prod_id->{prod_id});
}
my $serve_url = sprintf ("serve_image.cgi?product_id=%s;picture",
+ escape ($ref->{product_id}));
# generate a form allowing a quantity of the item to be added
# to the cart
push (@row, start_form(-method=>'POST', -action=>url()),
hidden( -name => "choice", -override => 1,
-default => "add" ),
hidden( -name => "prod_id", -override => 1,
-default => escapeHTML($ref->{prod_id})),
Tr ({-style=>"font-family: verdana; font-size: 10pt;"},
td (img ({-src => $serve_url, -alt => escapeHTML($ref->{product_id}
+)})),
td ({-width=>"80", -valign=>"top", -align => "center"}, escapeHTML(
+ $ref->{prod_id} )),
td ({-width=>"190", -valign=>"top"}, escapeHTML( $ref->{description
+} ))),
td (" "),
Tr ({-style=>"font-family: verdana; font-size: 10pt;"},
td ({-colspan => "3", -align => "right", -style=>"font-weight: 700;
+ color:blue;"}, "Price: \$", escapeHTML( sprintf( "%.2f", $ref->{pri
+ce}))),
Tr ({-style=>"font-family: verdana; font-size: 10pt;"},
td ({-colspan => "3", -align => "right"}, "Colors:", popup_menu( -n
+ame => "color", -values => $ref->{color}))),
Tr ({-style=>"font-family: verdana; font-size: 10pt;"},
td ({-colspan => "3", -align => "right"}, "Quantity:", popup_menu(
+-name => "quantity", -values => ["1", "2", "3", "4", "5", "6", "7", "
+8", "9"])),
td (image_button( -name => "Add Item", -src=>"../images/add.jpg", -
+border=>"0" )))),
Tr ({-valign=>"top"},
td ({-colspan=>"7", -width=>"100%"}, hr)),
end_form()
);
}
$sth->finish ();
return undef unless @row; # no items?
return (table ({-border => 0, -align => "center", -style=>"font-fa
+mily: verdana; font-size: 10pt;"}, @row));
}
Thanks for your help.
Oh, just in case, here's the Add Item subroutine.
sub add_item
{
my ($dbh, $cart_ref, $prod_id, $qty, $color) = @_;
# If the item isn't already in the cart, look it up from the datab
+ase
# and store it in the cart as a new entry with a quantity of zero.
if (!exists ($cart_ref->{$prod_id}))
{
my $sth = $dbh->prepare ("SELECT * FROM catalog_pet, item WHER
+E catalog_pet.product_id = item.prod_id AND prod_id = ?");
$sth->execute ($prod_id);
my $item_ref = $sth->fetchrow_hashref ();
$sth->finish ();
return if !defined ($item_ref); # this shouldn't happen...
$cart_ref->{$prod_id} = {}; # create new entry, indexed by
+item ID
$cart_ref->{$prod_id}->{description} = $item_ref->{description
+};
$cart_ref->{$prod_id}->{price} = $item_ref->{price};
$cart_ref->{$prod_id}->{qty} = 1;
}
$cart_ref->{$prod_id}->{qty} = $qty;
$cart_ref->{$prod_id}->{color} = $color;
}
| [reply] [d/l] [select] |
Okay, a brief lesson on references: you can do anything to the array pointed at by a reference that you could do to the array itself. So, the following two snippets do exactly the same thing (one to an array, the other to a referenced array):
# create and fool around with an array
my @rray = ();
$rray[0] = "foo";
push @rray, "bar";
print $rray[1], "\n";
# prints "bar"
# create and fool around with an arrayref
my $arrayref = [];
$arrayref->[0] = "foo";
push @$arrayref, "bar";
print $arrayref->[1], "\n";
#prints "bar"
So as you can see, using an arrayref is just an indirect way of using an array, with the added benefit that the reference can be passed around like a scalar, and put into arrays and hashes, and all sorts of fun stuff like that.
So, back to your problem. You wind up with $ref (which happens to be a reference to a hash). You're already pulling out values like $ref->{item_id} and $ref->{description}, so now you need to make $ref->{color} an arrayref and iterate over it. Here's the part of your code that takes the record set and turns it into a table. The HTML looks kinda b0rked... Please forgive me if I screw it up more.
while (my $ref = $sth->fetchrow_hashref ()) {
### NEW CODE ###
# Start up a new query
$clref = $dbh->prepare ("SELECT color FROM colors WHERE item_id =
+".$ref->{item_id});
$clref->execute;
# Push each new colour onto the array referenced by
# $ref->{color}
while (my $color = $clref->fetchrow_hashref()) {
push @{$ref->{color}}, $color->{color};
}
# Now $ref->{color} is an arrayref full of colours.
### ### ### ###
my $serve_url = sprintf ("serve_image.cgi?item_id=%s;picture", esc
+ape ($ref->{item_id}));
# generate a form allowing a quantity of the item to be added
# to the cart
push (@row,
start_form(-method=>'POST', -action=>url())),
hidden( -name => "choice", -override => 1, -default => "add" )
+,
hidden( -name => "item_id", -override => 1, -default => escape
+HTML($ref->{item_id})),
Tr ({-style=>"font-family: verdana; font-size: 10pt;"},
td (
img ({-src => $serve_url, -alt => escapeHTML($ref->{it
+em_id})})
),
td ({-width=>"80", -valign=>"top", -align => "center"},
escapeHTML( $ref->{item_id} )
),
td ({-width=>"190", -valign=>"top"},
escapeHTML( $ref->{description} )
)
),
Tr ({-style=>"font-family: verdana; font-size: 10pt;"},
td ({-colspan => "3", -align => "right", -style=>"font-wei
+ght: 700; color:blue;"},
"Price: \$",
escapeHTML(
sprintf( "%.2f", $ref->{price})
)
)
),
Tr ({-style=>"font-family: verdana; font-size: 10pt;"},
# Here is where you need to RTFM. At this point,
# $ref->{color} is an arrayref. I suspect that
# the popup_menu procedure will accept an array
# reference as an argument, but I'm not sure.
# Also, I'm too lazy to RTFM myself :o) In any
# case, if you need to give it an array instead
# you can dereference the arrayref. Check the
# links below for how to do that.
td ({-colspan => "3", -align => "right"},
"Colors:",
popup_menu( -name => "color", -values => $ref->{color}
+)
)
),
Tr ({-style=>"font-family: verdana; font-size: 10pt;"},
td ({-colspan => "3", -align => "right"},
"Quantity:",
popup_menu( -name => "quantity", -values => ["1", "2",
+ "3", "4", "5", "6", "7", "8", "9"])
),
td (
image_button( -name => "Add Item", -src=>"../images/ad
+d.jpg", -border=>"0" )
)
),
Tr ({-valign=>"top"},
td ({-colspan=>"7", -width=>"100%"},
hr
)
),
end_form()
);
}
For more information on references and how to use them (from people who know a whole lot more than me) See:
The 'references' tutorial by busunsl
References quick reference by tye
LAI
:eof
| [reply] [d/l] [select] |