Gossamer Forum
Home : General : Perl Programming :

printing non display

Quote Reply
printing non display
I am leaning GI-Session-mysql

http://search.cpan.org/.../Session/CookBook.pm

below code confused me why it display only
Total Price:(this was printed):$total_price>

while the cart detail has been non displayed while it has exist in cart.



sub display_cart {
my ($cgi, $session) = @_;

# getting the cart's contents
my $cart = $session->param("CART") || [];
my $total_price = 0;
my $RV = q~<table><tr><th>Title</th><th>Price</th></tr>~;

if ( $cart ) {
for my $product ( @{$cart} ) {
$total_price += $product->{price};



$RV = qq~
<tr>
<td>$product->{name} **$product->{price}</td>
<td>$product->{price}</td>
</tr>~;
}

} else {
$RV = qq~
<tr>
<td colspan="2">There are no items in your cart
yet</td>
</tr>~;
}

$RV = qq~
<tr>
<td><b>Total Price:(this was printed):</b></td>
<td><b>$total_price></b></td>
</tr></table>~;

return $RV;

}

Last edited by:

courierb: Sep 23, 2004, 7:12 AM
Quote Reply
Re: [courierb] printing non display In reply to
You're overwriting $RV instead of appending it. You should be using $RV .= ... after you set it initially.

~Charlie
Quote Reply
Re: [Chaz] printing non display In reply to
Yes, now it works. thank you.
Quote Reply
Re: [courierb] printing non display In reply to
No worries

~Charlie
Quote Reply
Re: splice In reply to
Dear Mr Charlie


below code supposed to delete the element from the array
when $product->{itemID} == $itemID ,

however it alway delete the first element.
it seems that $idx is not been self countup. was any error?
as it seems i can not find the problem now.

Thanks in advance


sub remove_item {
my ($cgi, $session) = @_;
# getting the itemID from the CGI parameter
my $itemID = $cgi->param("itemID") or return undef;
# getting the cart data from the session
my $cart = $session->param("CART") or return undef;
my $idx = 0;
for my $product ( @{$cart} ) {
$product->{itemID} == $itemID or next;
splice( @{$cart}, $idx++, 1);
}
$session->param("CART", $cart);
return display_cart($cgi, $session);
print "$idx++\n\n";
}

Last edited by:

courierb: Sep 23, 2004, 9:02 AM
Quote Reply
Re: [courierb] splice In reply to
you're not incrementing $idx on every iteration. Try something like this:

Code:
for (0 .. $#$cart) {
splice( @$cart, $_, 1) if $cart->[$_]->{itemID} == $itemID;
}

If you know you only have one instance of that item in the cart you might want to add a last in there to stop processing:

Code:
for (0 .. $#$cart) {
splice( @$cart, $_, 1), last if $cart->[$_]->{itemID} == $itemID;
}

~Charlie

Last edited by:

Chaz: Sep 23, 2004, 9:54 AM
Quote Reply
Re: [Chaz] splice In reply to
Dear Charlie ,

Thanks for the code. however i am confused now as my code is from cgi-session CookBook.
it should be used by many people. and it seems that no major error there.
however why no incrementing $idx on every iteration? according the code, it should increase
the counting .

could you or anyone elase light me about this issue?

Thanks
Quote Reply
Re: [courierb] splice In reply to
Code:
my $idx = 0;
for my $product ( @{$cart} ) {
$product->{itemID} == $itemID or next;
splice( @{$cart}, $idx++, 1);
}

You are using $idx to keep track of the array index you are processing but it only gets updated when the item IDs match. The first line in your for loop exits the current iteration unless the item numbers match and $idx never gets incremented. Once the item numbers do match $idx is still at 0 causing the first element of the array to get spliced out. Here are a couple of examples that will get your code working:

Code:
my $idx = 0;
for my $product ( @{$cart} ) {
$idx++;
$product->{itemID} == $itemID or next;
splice( @{$cart}, $idx - 1, 1);
}

Code:
my $idx = 0;
for my $product ( @{$cart} ) {
splice( @{$cart}, $idx, 1) if $product->{itemID} == $itemID;
$idx++;
}

or the one I posted above...

~Charlie
Quote Reply
Re: [Chaz] splice In reply to
Thanks Charlie,

the solution is working.
however according the code
when
$product->{itemID} == $itemID
the mathing one will be splice out.

for my testing ,
item itemID
item1 1001
item1 1001
item1 1001
item1 1001
item1 1001
item1 1001
item2 1002
item3 1003

when i delete itemID 1001, logically, it should delete all item when itemID matchs 1001
however testing result is:
item1 1001
item1 1001
item1 1001
item2 1002
item3 1003
not all is deleted. and do again, it splice another two itemID 1001, the result looks like
item1 1001
item2 1002
item3 1003

why?
Quote Reply
Re: [courierb] splice In reply to
In Reply To:
Thanks Charlie,

the solution is working.
however according the code
when
$product->{itemID} == $itemID
the mathing one will be splice out.

for my testing ,
item itemID
item1 1001
item1 1001
item1 1001
item1 1001
item1 1001
item1 1001
item2 1002
item3 1003

when $itemID =1001
, logically, it should delete all item when itemID matchs 1001

however testing result is:
item1 1001
item1 1001
item1 1001
item2 1002
item3 1003
not all is deleted. and do again, it splice another two itemID 1001, the result looks like
item1 1001
item2 1002
item3 1003

why?
Quote Reply
Re: [courierb] splice In reply to
Which code did you use? I posted three or four examples. One of those examples will only delete the first occurrence of that item. Post your current code so I can look at it.

~Charlie
Quote Reply
Re: [Chaz] splice In reply to
Dear Charlie , i have tried last two method and get the same result.
if there is 6 same itemID in the cart, when do a remove_item action,
it first time will remove only half of them ( three)
if there is 8 same itemID in the cart, when do a remove_item action,
it first time will remove only half of them ( four)

sub remove_item {
my ($cgi, $session) = @_;
# getting the itemID from the CGI parameter
my $itemID = $cgi->param("itemID") or return undef;
# getting the cart data from the session
my $cart = $session->param("CART") or return undef;
# my $idx = 0;
#for my $product ( @{$cart} ) {

# $product->{itemID} == $itemID or next;

# splice( @{$cart}, $idx++, 1);
#}
#my $idx = 0; for my $product ( @{$cart} ) { splice( @{$cart}, $idx, 1) if $product->{itemID} == $itemID; $idx++; }
my $idx = 0; for my $product ( @{$cart} )
{ $idx++; $product->{itemID} == $itemID or next; splice( @{$cart}, $idx - 1, 1); }

$session->param("CART", $cart);
return display_cart($cgi, $session);

}
Quote Reply
Re: [courierb] splice In reply to
after a testing, below splice for below array works exactly as expected.
when do a remove_item action for ITEMID is 1001, it will remove all
item which itemID=1001.

item1 1001
item2 1002

item3 10013
item1 1001
item2 1002
item3 10013
item1 1001
item2 1002
item3 10013


while it will only remove two of item1 from array when the card content is in below order.
item1 1001
item1 1001
item1 1001
item1 1001
item2 1002
item3 10013
item2 1002
item3 10013

item2 1002
item3 10013

Quote Reply
Re: [courierb] splice In reply to
Ugg, splice is altering the original array which is throwing off the index. I didn't even think about that, sorry :) Try using grep:

Code:
@{$cart} = grep { $_->{itemID} != $itemID } @{$cart};

Here is what I get:

Code:
Before: $VAR1 = [
{
'itemID' => 1001
},
{
'itemID' => 1001
},
{
'itemID' => 1001
},
{
'itemID' => 1001
},
{
'itemID' => 1001
},
{
'itemID' => 1002
},
{
'itemID' => 1003
}
];
After: $VAR1 = [
{
'itemID' => 1002
},
{
'itemID' => 1003
}
];

with this code:

Code:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;

my $itemID = 1001;
my $cart = [
{itemID => 1001},
{itemID => 1001},
{itemID => 1001},
{itemID => 1001},
{itemID => 1001},
{itemID => 1002},
{itemID => 1003},
];

print 'Before: ';
print Dumper($cart);
@{$cart} = grep { $_->{itemID} != $itemID } @{$cart};
print 'After: ';
print Dumper($cart);

~Charlie
Quote Reply
Re: [Chaz] splice In reply to
Thanks, it works great.

i wonder if any one has any sample cart code regarding cgi-session?
as it seems that there are some some errors in the sample code from cookbook., i now have to added
array element replacement function by splice , as this function is lack in the cookbook.


Charlie . thanks again. you are great.

Last edited by:

courierb: Sep 25, 2004, 5:05 AM
Quote Reply
Re: [courierb] splice In reply to
All you need to do to add an item is to push it onto your $cart arrayref:

Code:
push @{$cart}, $item_hash_ref;

~Charlie
Quote Reply
Re: [Chaz] splice In reply to
Thanks Charlie . i mean update a array element. now i am using splice to do that function
to update cart item quantity.

there is another question. i have tried a sample code from
http://search.cpan.org/~sherzodr/CGI-Session-3.95/Session/CookBook.pm
which is MEMBERS AREA login.
I have the problem, CGI::Session login failed --session info not being stored.
It has been addressed at http://forums.devshed.com/t101620/s.html,

since i am a beginer , i now can not find where the problem is . could any one here
help me out?

here is the code i used for testing from cookbook.
suppose you're storing profile in flat files in the following format:
username password email


Code:


#####code begin
init($cgi, $session);

if ( $session->param("~login-trials") >= 3 ) {
print error("You failed 3 times in a row.\n" .
"Your session is blocked. Please contact us with ".
"the details of your action");
exit(0);

}

unless ( $session->param("~logged-in") ) {
print login_page($cgi, $session);
exit(0);

}

sub init {
my ($session, $cgi) = @_; # receive two args

if ( $session->param("~logged-in") ) {
return 1; # if logged in, don't bother going further
}

my $lg_name = $cgi->param("lg_name") or return;
my $lg_psswd=$cgi->param("lg_password") or return;

# if we came this far, user did submit the login form
# so let's try to load his/her profile if name/psswds match
if ( my $profile = _load_profile($lg_name, $lg_psswd) ) {
$session->param("~profile", $profile);
$session->param("~logged-in", 1);
$session->clear(["~login-trials"]);
return 1;

}

# if we came this far, the login/psswds do not match
# the entries in the database
my $trials = $session->param("~login-trials") || 0;
return $session->param("~login-trials", ++$trials);
}


sub _load_profile {
my ($lg_name, $lg_psswd) = @_;

local $/ = "\n";
unless (sysopen(PROFILE, "profiles.txt", O_RDONLY) ) {
die "Couldn't open profiles.txt: $!");
}
while ( <PROFILES> ) {
/^(\n|#)/ and next;
chomp;
my ($n, $p, $e) = split "\s+";
if ( ($n eq $lg_name) && ($p eq $lg_psswd) ) {
my $p_mask = "x" . length($p);
return {username=>$n, password=>$p_mask, email=>$e};

}
}
close(PROFILE);

return undef;
}
Quote Reply
Re: [courierb] splice In reply to
Quote:
I have the problem, CGI::Session login failed --session info not being stored.[/code]
Are you setting a cookie somewhere with the session ID to keep state? Can you see the session being saved at all?

~Charlie
Quote Reply
Re: [Chaz] splice In reply to
   

i call sub init on top of other scripts.
and folowed by cart script.

Can't call method "param" on an undefined value at F:\webtest\test\cgi-bin\help3\test\session7.pl line 220.
while line 220 is under sub init. script did not create session for this case. as it found error.
sub init {
my ($session, $cgi) = @_; # receive two args
if ( $session->param("~logged-in") ) { # this is line 220********************************
return 1; # if logged in, don't bother going further
}
my $lg_name = $cgi->param("lg_name") or return;
my $lg_psswd=$cgi->param("lg_password") or return;
# if we came this far, user did submit the login form
# so let's try to load his/her profile if name/psswds match
if ( my $profile = _load_profile($lg_name, $lg_psswd) ) {
$session->param("~profile", $profile);
$session->param("~logged-in", 1);
$session->clear(["~login-trials"]);
return 1;
}
# if we came this far, the login/psswds do not match
# the entries in the database
my $trials = $session->param("~login-trials") || 0;
return $session->param("~login-trials", ++$trials);
}
Quote Reply
Re: [courierb] splice In reply to
Quote:
Can't call method "param" on an undefined value at F:\webtest\test\cgi-bin\help3\test\session7.pl line 220.

Your session object does not exist where you are calling init. You need to debug your script and find out why the session object doesn't exist at that point.

~Charlie
Quote Reply
Re: [Chaz] splice In reply to
This really puzzled me asi pull all code from the sample code from http://search.cpan.org/.../Session/CookBook.pm
and alway got some error, the worst thing is i even do not know how to correct it.

Code:
#!/usr/bin/perl -W
# member area session login
# http://help3/test/session5.pl?cmd=add;itemID=1001
#
use CGI::Session;
use CGI::Session::MySQL;
use CGI qw(:standard);
use CGI::Carp qw(fatalsToBrowser);
use DBI;

$host = "localhost";
$db_user = "db_user";
$db_password = "password";
$db = "cart";

my $cgi;
my $session;
my $cart;
$cgi = new CGI;

my $dbh = DBI->connect("dbi:mysql:$db:$host", "$db_user", "$db_password", {RaiseError => 0, PrintError => 0} ) ;
####create session object
$sid = $cgi->cookie('CGISESSID') || $cgi->param('CGISESSID') || undef;
$session = new CGI::Session("driver:MySQL", $sid, {Handle=>$dbh});
#$session->param("~logged-in", 1);
$session->param("~login-trials", 1);


init($cgi, $session);

if ( $session->param("~login-trials") >= 3 ) {
print error("You failed 3 times in a row.\n" .
"Your session is blocked. Please contact us with ".
"the details of your action");
exit(0);

}

unless ( $session->param("~logged-in") ) {
print login_page($cgi, $session);
exit(0);

}
###############

sub init {
my ($session, $cgi) = @_; # receive two args

if ( $session->param("~logged-in") ) {
return 1; # if logged in, don't bother going further
}

my $lg_name = $cgi->param("lg_name") or return;
my $lg_psswd=$cgi->param("lg_password") or return;

# if we came this far, user did submit the login form
# so let's try to load his/her profile if name/psswds match
if ( my $profile = _load_profile($lg_name, $lg_psswd) ) {
$session->param("~profile", $profile);
$session->param("~logged-in", 1);
$session->clear(["~login-trials"]);
return 1;

}

# if we came this far, the login/psswds do not match
# the entries in the database
my $trials = $session->param("~login-trials") || 0;
return $session->param("~login-trials", ++$trials);
}

sub login_page {
print "Hello . this is login page! ";
}

sub _load_profile {
my ($lg_name, $lg_psswd) = @_;

return {username=>'austin', password=>'mypass', email=>'email'};
#return undef;
}

Last edited by:

courierb: Sep 29, 2004, 1:44 AM