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

I've got an odd situation here, where I'm not sure if mod_perl is coming into play or not (as it's compiled into my httpd, but not configured in httpd.conf). Please bear with me as I explain the complexities.

I've got a script that's fetching quiz questions and answers out of a database and displaying them to the browser; said script later checks the user's answer and gives them a reply.

Since I figured I'd be talking to the database a lot, I made my database handle a global variable (or at least I think I did; I'm using strict, and I declared it as "my $dbh = DBI->connect..." outside of any subroutine or block). I've been able to use it with no problems throughout the script, including on different calls to the script (i.e. on the category display page of the quiz, the question display page, and the answer page).

I also decided to make the reference generated by fetchrow_hashref() when I got each question global (by the same method), since I figured I'd be using it in many subroutines, through different requests.

When I first dereferenced objects out of the hash, everything worked great:
sub display_questions() { my $template = HTML::Template->new( filename => '/home/www/elderlinda/quiz-template.tmpl', die_on_bad_params => 0); $template->param(question => $qref->{question}, ans_a => $qref->{ans_a}, ans_b => $qref->{ans_b}, ans_c => $qref->{ans_c}, category => param("category"), number => $qref->{number} ); print $template->output; }
This displayed the page with the question and possible answers nicely. Note that I did not ever call the same key twice out of the hash.

When I attempted to dereference a key for the second time out of the hash, I got an empty value:
sub check_answer() { my $subans = param("ANS"); my $qnum = $qref->{number}; ... }

Would this be because hash references are transient? Or would it be because dereferencing a key twice makes a second call to fetchrow_hashref()? Any ideas how I would fix this?

Thanks,
Alex Kirk

Replies are listed 'Best First'.
(Ovid) Re: Second Dereference of Hash Ref from fetchrow_hashref broken
by Ovid (Cardinal) on Dec 31, 2001 at 02:12 UTC

    schnarff wrote:

    I made my database handle a global variable (or at least I think I did; I'm using strict, and I declared it as "my $dbh = DBI->connect..." outside of any subroutine or block).

    This is a common misunderstanding. A global variable is one that is visible throughout all of the program because it sits in a typeglob slot in the symbol table. Package %Foo:: can see globals in package %Bar:: by appending the package name: $Bar::global_baz. If you really need global variables, you want to use the vars pragma. However, since you are using mod_perl, globals are generally not a good thing.

    By declaring your variables with my, you are lexically scoping them. With what you have described, if they are declared outside of any subroutine or block, they will be file-scoped -- that is, visible throughout the entire file they are in, from the point they are declared, irrespective of package boundaries.

    As for your immediate problem, you asked if the second access to the hashref is empty "because hash references are transient". In order for a hash value to dissapear, one (or more) of a few things need to occur:

    1. The scalar containing the hashref ($qref, in this case) has had something else assigned to it.
    2. The specific hash value has had something else assigned to it (e.g. $qref->{number} = '').
    3. Another scalar contains a reference to the same hash and is doing something to it (that would probably be a Bad Thing).

    As for items one and two, is there any chance that you accidentally made another call to fetchrow_hashref()? You have to have some sort of hash reference in $qref or else Perl is going to complain about using that variable as a hash reference, if you are using strict.

    Another thought: are you sure that you are calling check_answer()? and that it's getting called when you expect it to? That's the only other thing that I can think of, as what you have posted looks fine. Perhaps you should post more code?

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.