ukndoit has asked for the wisdom of the Perl Monks concerning the following question:

I cannot get this to work to save my life...

I created a cron job to run every night and process autoship orders.
Here is a partial sample of my code:
my $_todayIs = Format_Date_For_Viewing(time(),"day_only"); my $sth = $dbh->prepare(qq{SELECT * FROM `autoship_orders` WHERE `day` + = ?}); $sth->execute($_todayIs); my $_cnt = 0; my $_suc = 0; my $_fai = 0; while(my $_sao = $sth->fetchrow_hashref()) { $_cnt++; my %_billingInfo = (); my $sth2 = $dbh->prepare(qq{SELECT * FROM `secured_data` WHERE `si +d` = ? AND `Id` = ?}); $sth2->execute($_sao->{sid},$_sao->{Id}); my $_sd = $sth2->fetchrow_hashref(); $sth2->finish(); $sth2 = $dbh->prepare(qq{SELECT * FROM `reg_members` WHERE `Id` = +?}); $sth2->execute($_sao->{Id}); my $_regmem = $sth2->fetchrow_hashref(); $sth2->finish(); # Get Secure Data my $_billing = $_sd->{p11}; $_billing = decryptdata($_billing,$_encryptionKey); $_billing = decrypt($_billing); # Bunch of other code.... decryption ........ my @_billingData = split(/;/, $_billing); ($_billingFname,$_billingLname) = split / /, $_billingData[0], 2; $_billingInfo{fname} = $_billingFname; $_billingInfo{lname} = $_billingLname; $_billingInfo{address} = $_billingData[1]; # other code setting some other hash keys in %_billingInfo my $_cardCharged = chargeCard(\%_billingInfo); # That is what I have passed # Here is my chargeCard sub (top of it anyways): sub chargeCard { %_billingInfo = shift;
Anyhow, I created code to debug it, like this:
my $_debug = 1; open(BUG,">>/home/path/to/file") if $_debug; seek(BUG, 0, 2) if $_debug; print BUG qq~Started debugging at line: ~ . __LINE__ . "\n" if $_debug +; if($_debug) { foreach my $key (keys (%_billingInfo)) { print BUG escapeHTML ($key) . " = " . escapeHTML ($_billin +gInfo{$key}) . "\n"; } }
Now in the while statement readin the database, where I create it, it does print all the keys in the text file, but where I pass it, there is nothing. I have passed it these ways, all to no avail:

my $_cardCharged = chargeCard($_billingInfo); sub chargeCard { %_billingInfo = shift; # AND my $_cardCharged = chargeCard(\$_billingInfo); sub chargeCard { %_billingInfo = shift; # AND my $_cardCharged = chargeCard(%_billingInfo); sub chargeCard { %_billingInfo = shift; # AND my $_cardCharged = chargeCard(\%_billingInfo); sub chargeCard { %_billingInfo = shift; # AND every other way I can think of...
I am getting so frustrated, I cannot fingure out what I'm doing wrong. I pass hash's all the time, but I cannot get this to work to save my life. I'd appreciate any help you can be.

Thank you very much Richard

Replies are listed 'Best First'.
Re: passing hash to subroutine
by ikegami (Patriarch) on Sep 14, 2007 at 16:17 UTC

    The only thing that can be passed to a function is a list of scalars. Solutions:

    • You could pass a reference to the hash and use that:

      sub dump_hash { my ($hash) = @_; foreach my $key (keys %$hash) { print $key, '=>', $hash->{$key}, "\n"; } } dump_hash(\%hash);
    • You could convert the hash to a list, then recreate the hash:

      sub dump_hash { my %hash = @_; foreach my $key (keys %hash) { print $key, '=>', $hash{$key}, "\n"; } } dump_hash(%hash);
Re: passing hash to subroutine
by derby (Abbot) on Sep 14, 2007 at 16:20 UTC

    You're kinda mixing up pass by value and pass by reference. If you want to pass by value, then</strike

    In the method being invoked, you need to capture all the passed values, not just the the first one:

    chargeCard( %_billingInfo ); ... sub chargeCard { my %_billingInfo = @_; $_billingInfo{key} }
    but you'd probably be better of using a reference:
    chargeCard( \%_billingInfo ); ... sub chargeCard { my $_billingInfo = shift; $_billingInfo->{key}; }

    -derby

    update: Remove the whole passed by value/by ref. ikegami reminded me perl always passes by value and I was confusing *pass by reference* with *passing a reference.*

Re: passing hash to subroutine
by ukndoit (Sexton) on Sep 14, 2007 at 23:51 UTC
    Ok, here is how I fixed it:
    my $_passThis; foreach my $key (keys (%_billingInfo)) { $_passThis .= $key .'='. escapeHTML ($_billingInfo{$key}) . "^"; } my $_cardCharged = chargeCard($_passThis); # And at the subroutine I fixed it this way: sub chargeCard { my $_passedList = shift; my @_PassedL = split (/\^/, $_passedList); my %_billingHash = (); foreach my $_k (@_PassedL) { ($_key,$_value) = split /\=/, $_k, 2; $_billingHash{"$_key"} = $_value; }
    That worked! :o) Thank you guys for your advice of passing a list, just making 1 variable like a QUERY_STRING seperated instead of with a ^ instead of & because I might have a name of 'Rick & Chantelle' as a first name which would throw it off, so I used the ^ to seperate each.

    Thank you very much Richard