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

G'day all

I have written the following script, as an exercise in understanding how the DBI does (or doesn't) work.

The "mecury" database contains a table called "counter" which has one column "count". "count" currently holds the value 2. (set manually)

#!/usr/bin/perl -w # mercurus' counter script # version 0.9 # 21 April 2003 # Documentation to follow... # Before configuring this file, please run: ./configure.pl to establis +h the required mySQL table. # Modules. use strict; use CGI; use DBI; use CGI::Carp qw(fatalsToBrowser); # Added for debugging purposes. # Variables. my $db_database = "**********"; # The name of the mySQL database. my $db_username = "**********"; # The name of the mySQL user. my $db_password = "**********"; # The password for the mySQL user. # Main script. ## Connect to the mySQL database. my $dbh = &mysql_connect ($db_database,$db_username,$db_password); ## Print the current database value. my $current_count = &print_current ($dbh); ## Increment the database value. my $exit_code = &increment ($dbh,$current_count); ## Exit. if ($exit_code == 0) { exit; } else { die "Unknown error. Execution failed, but database updated.\n"; + } # Subroutines. ## Current database value printing subroutine. sub print_current { my $dbh = (@_); ## Retrieve information from the database. my $sth_1 = $dbh->prepare ("SELECT count FROM counter;"); $sth_1->execute || die "$dbh->errstr()"; while (my $fields = $sth_1->fetchrow_arrayref()) { my $current = $fields->[0]; } ## Display that information for the user. print "Content-type: text/html\n\n"; print "$current others have gathered information here.\n"; return ($current); } ## Current database value incrementing subroutine. sub increment { my ($dbh,$current) = (@_); ## Increment the previous value. my $updated = $current + 1; ## Write the new value to the database. my $sth_2 = $dbh->prepare ("UPDATE counter SET count='$updated' WHERE +count='$current';"); $sth_2->execute || die "$dbh->errstr()"; return ($exit_code); } ## MySQL database connecting subroutine. sub mysql_connect { my ($db_name,$username,$password) = (@_); ## Connect to the database with the values supplied. my $dbh = DBI->connect("DBI:mysql:$db_name","$username","$password"); return ($dbh); } # End of file.
Unfortunately, the error produced is:
Global symbol "$current" requires explicit package name at 
     /var/www/cgi-bin/hit_counter.cgi line 54.

Global symbol "$current" requires explicit package name at 
     /var/www/cgi-bin/hit_counter.cgi line 56.
As far as I can tell, the value of $current is initialised on line 49 ... or do I have scoping issues outside of the while loop ?

Can anyone point me to a solution ?
(I've read the DBI perldoc and some basic DBI tutorials from a few places - including here, to no avail...)

Thanks in advance
mercurus

edited: Sun Apr 27 19:19:56 2003 by jeffa - readmore tag, formatted error message

Replies are listed 'Best First'.
Re: Initialised values that fail to initialise..?
by Enlil (Parson) on Apr 26, 2003 at 08:56 UTC
    As far as I can tell, the value of $current is initialised on line 49 ... or do I have scoping issues outside of the while loop ?

    The behavior you are noticing has nothing to do with DBI ,but rather as you have guessed, with scoping. perlintro - variable scoping will be a better place to start to look for information, after which you might want to read Coping with Scoping as well... hope this helps

    -enlil

Re: Initialised values that fail to initialise..?
by Abigail-II (Bishop) on Apr 26, 2003 at 09:04 UTC
    You don't tell us what line 49 is, and I'm not going to count 49 lines. But my guess is that it is:
    print "$current others have gathered information here.\n";

    The value cannot be initialized, because you are getting a compile time error. And you are getting that because in that line, no variable $current has been declared.

    If you properly indent your code, it will become obvious.

    Abigail

      You're right, but I'll comment a number next to the relevant lines in future.

      But my code IS properly indented, unfortunately copying + pasting in blackbox appears to have let me down... sorry.

      The problem was indeed scoping, sorted.

      Cheers
      mercurus

Re: Initialised values that fail to initialise..?
by atnonis (Monk) on Apr 26, 2003 at 11:33 UTC
    try declaring the variable at the start of your sub
    sub print_current { my $dbh = (@_); my $current =''; #same as undef ## Retrieve information from the database. my $sth_1 = $dbh->prepare ("SELECT count FROM counter;"); $sth_1->execute || die "$dbh->errstr()"; while (my $fields = $sth_1->fetchrow_arrayref()) { $current = $fields->[0]; } ## Display that information for the user. print "Content-type: text/html\n\n"; print "$current others have gathered information here.\n"; return ($current); }