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

In the program listed below I have two global variables that don't work like I want. @ContactIDList is a list of ID numbers that is collected in a subroutine. I can print out the list in the subroutine, but not in the if statement from which I call the subroutine. $CurIDPtr is supposed to keep track of which ID is being used currently, but in the outer if statement it's value is always 0. I assumed this was a scoping problem and changed the declarations to use 'our' but that hasn't helped. Appreciate any help on this. Here is my code:
#!/usr/bin/perl -w # Russell Hyland # WebHortLine SearchContacts.cgi # # Prompt for search string, then get a list of ContactIDs of Contact r +ecords that contain the searchstring in # one or more fields. Use the list to display the records. use strict; use warnings; use CGI::Carp qw(); use CGI::Pretty; use CGI qw(:standard :cgi-lib -debug fatalsToBrowser); use DBD::mysql; use DBI; my $cgi = new CGI; my @css = (Link({-rel=>'stylesheet',-type=>'text/css',-src=>'Styles.cs +s',-media=>'screen'})); my ($dbh, $selectstr, $sth, @row); my $SrchStr; our @ContactIDList; our $CurIDPtr = 0; my $County = $cgi->cookie('MG_HortLine'); if (!$County) { print redirect(-location=>"http://hortline.rbhyland.org/Login.cgi" +); } print $cgi->header(); print start_html(-title =>'Search Contacts', -style =>'Styles.css', -script=>{-language=>'JAVASCRIPT', -src=>'Scripts.js'}); print "<img src='http://www.hortline.rbhyland.org/MGLogo.jpg' alt='MG +logo' align='left' />"; print "<h1>&nbsp;Penn State Consumer<br /><br />&nbsp;Horticultural He +lp Line</h1><br />"; print h2('Search Contacts'),hr; if (!param('SearchFld') && !param('Next') && !param('Prev')) { print start_form, "<label for='SearchFld'>Search </label>", textfield(-name=>'SearchFld',-value=>"",-size=>30,-maxlength +=>50,-id=>'SearchFld', -class=>'DataIn'), br,br,submit, end_form; } elsif (param('Next')) { $CurIDPtr += 1; print '[',$CurIDPtr,'][',$ContactIDList[$CurIDPtr],']'; DisplayRec(); } elsif (param('Prev')) { $CurIDPtr = $CurIDPtr - 1; print Dump; print '[',$CurIDPtr,'][',$ContactIDList[$CurIDPtr],']'; DisplayRec(); } else { getIDs(); DisplayRec(); } print end_html;
sub DisplayRec { $dbh = DBI->connect("DBI:mysql:database=hortline;host=mysql.hortli +ne.rbhyland.org","rbhyland","dh_R95w") or &dienice("Database logon failed: $DBI::errs +tr\n"); $selectstr = "SELECT * ". "FROM Contacts ". "WHERE ContactID = ?; "; $sth = $dbh->prepare("$selectstr"); $sth->execute("$main::ContactIDList[$main::CurIDPtr]") or &dbdie; @row = $sth->fetchrow_array(); &dienice("Data fetching error: $DBI::errstr\n") if $DBI::err; my $FirstName = $row[2]; my $LastName = $row[3]; my $Address = $row[4]; my $City = $row[5]; my $State = $row[6]; my $Zip = $row[7]; my $Muni = $row[8]; my $ClientType = $row[9]; my $Phone = $row[10]; my $EmailName = $row[11]; my $ContactMethodPhone = $row[12]; my $ContactMethodWalkIn = $row[13]; my $ContactMethodEmail = $row[14]; my $ContactMethodEvent = $row[15]; my $Answer = $row[16]; my $Question = $row[17]; my $MasterGardener = $row[18]; my $CallDate = $row[19]; my $InfoProvidedVerbally = $row[20]; my $InfoProvidedFaxed = $row[21]; my $InfoProvidedMailed = $row[22]; my $InfoProvidedHandout = $row[23]; my $InfoProvidedWebsite = $row[24]; my $SampleStatusDue = $row[25]; my $SampleStatusReceived = $row[26]; my $SampleStatusSentToPSU = $row[27]; my $CallCompleteDate = $row[28]; my $CallBackDate = $row[29]; my $MGCallBack = $row[30]; my $FactSheets = $row[31]; my $Topic = $row[32]; print "<label for='FirstNameFld'>Name</label>", textfield(-name=>'FirstNameFld',-value=>$FirstName,-size=> +50,-maxlength=>50, -id=>'FirstNameFld', -readonly=>'readonly', -c +lass=>'DataIn'), # br, # "<label for='LastNameFld'>Last Name</label>", textfield(-name=>'LastNameFld',-value=>$LastName, -size=>50,-maxlength=>50,-id=>'LastNameFld', -read +only=>'readonly', -class=>'DataIn2'), br, "<label for='AddressFld'>Address</label>", textfield(-name=>'AddressFld',-value=>$Address, -size=>50,-maxlength=>50,-id=>'AddressFld', -reado +nly=>'readonly', -class=>'DataIn'), # br, # "<label for='CityFld'>City</label>", textfield(-name=>'CityFld',-value=>$City, -size=>50,-maxlength=>50,-id=>'CityFld', -readonly +=>'readonly', -class=>'DataIn2'), # br, # "<label for='StateFld'>State</label>", textfield(-name=>'StateFld',-value=>$State, -size=>2,-maxlength=>2,-id=>'StateFld', -readonly= +>'readonly', -class=>'DataIn3'), # br, # "<label for='ZipFld'>Zip</label>", textfield(-name=>'ZipFld',-value=>$Zip, -size=>10,-maxlength=>10,-id=>'ZipFld', -readonly= +>'readonly', -class=>'DataIn4'), br, "<label for='MuniFld'>Municipality</label>", textfield(-name=>'MuniFld',-value=>$Muni, -size=>50,-maxlength=>50,-id=>'MuniFld', -readonly +=>'readonly', -class=>'DataIn'), br, "<label for='EmailFld'>Email</label>", textfield(-name=>'EmailFld',-value=>$EmailName, -size=>50,-maxlength=>50,-id=>'EmailFld', -readonl +y=>'readonly', -class=>'DataIn'), br, "<label for='PhoneFld'>Phone</label>", textfield(-name=>'PhoneFld',-value=>$Phone, -size=>20,-maxlength=>20,-id=>'PhoneFld', -readonl +y=>'readonly', -class=>'DataIn'), br, "<label for='ClientTypeFld'>Client Type</label>", textfield(-name=>'ClientTypeFld',-value=>$ClientType, -size=>20,-maxlength=>20,-id=>'ClientTypeFld', -re +adonly=>'readonly', -class=>'DataIn'), br, "<label for='CallDateFld'>Call Date </label>", textfield(-name=>'CallDateFld',-value=>$CallDate,-size=> +10,-maxlength=>10,-id=>'CallDateFld', -class=>'DataIn', -readonly=>'readonly'), br, "<label for='CallBackDateFld'>Call Back </label>", textfield(-name=>'CallBackDateFld',-value=>$CallBackDate +,-size=>10,-maxlength=>10, -id=>'CallBackDateFld',-class=>'DataIn', -re +adonly=>'readonly'), br, "<label for='CallCompleteDateFld'>Call Complete </label>", textfield(-name=>'CallCompleteDateFld',-value=>$CallComp +leteDate,-size=>10,-maxlength=>10, -id=>'CallCompleteDateFld',-class=>'DataIn', + -readonly=>'readonly'), br, "<label for='SampleStatusDue'>Sample Status </label>", checkbox(-name=>'SampleStatusDue',-checked=>$SampleStatusD +ue?1:0, -value=>$SampleStatusDue,-label=>'Waiting/Clie +nt', -readonly=>'readonly'), ' ', checkbox(-name=>'SampleStatusReceived',-checked=>$SampleSt +atusReceived?1:0, -value=>$SampleStatusReceived,-label=>'Receive +d', -readonly=>'readonly'), ' ', checkbox(-name=>'SampleStatusSentToPSU',-checked=>$SampleS +tatusSentToPSU?1:0, -value=>$SampleStatusSentToPSU,-label=>'Sent T +o PSU', -readonly=>'readonly'), br, "<label for='QuestionFld'>Question</label>", textarea(-name=>'QuestionFld',-value=>$Question,-rows= +>10,-columns=>50,-class=>'DataIn', -readonly=>'readonly'), br,br,br,br,br,br,br,br,br, "<label for='AnswerFld'>Answer</label>", textarea(-name=>'AnswerFld',-value=>$Answer,-rows=>10, +-columns=>50,-class=>'DataIn', -readonly=>'readonly'), br,br,br,br,br,br,br,br,br, "<label for='ContactMethodPhone'>Contact Methods</label>", checkbox(-name=>'ContactMethodPhone',-checked=>$ContactMet +hodPhone?1:0, -value=>'1',-label=>'Phone', -readonly=>'reado +nly'), ' ', checkbox(-name=>'ContactMethodWalkIn',-checked=>$ContactMe +thodWalkIn?1:0, -value=>'1',-label=>'Walk In', -readonly=>'rea +donly'), ' ', checkbox(-name=>'ContactMethodEmail',-checked=>$ContactMet +hodEmail?1:0, -value=>'1',-label=>'Email', -readonly=>'reado +nly'), ' ', checkbox(-name=>'ContactMethodEvent',-checked=>$ContactMet +hodEvent?1:0, -value=>'1',-label=>'Event', -readonly=>'reado +nly'), br, "<label for='IPVerbally'>Information Provided</label>", checkbox(-name=>'IPVerbally',-checked=>$InfoProvidedVerbal +ly?1:0, -value=>'1',-label=>'Verbally', -readonly=>'re +adonly'), " ", checkbox(-name=>'IPFaxed',-checked=>$InfoProvidedFaxed?1:0 +, -value=>'1',-label=>'Faxed', -readonly=>'reado +nly'), " ", checkbox(-name=>'IPMailed',-checked=>$InfoProvidedMailed?1 +:0, -value=>'1',-label=>'Mailed', -readonly=>'read +only'), " ", checkbox(-name=>'IPHandout',-checked=>$InfoProvidedHandout +?1:0, -value=>'1',-label=>'Handout', -readonly=>'rea +donly'), " ", checkbox(-name=>'IPWebsite',-checked=>$InfoProvidedWebsite +?1:0, -value=>'1',-label=>'Website', -readonly=>'rea +donly'), br, '<label for="MGFld">Initial Call MG </label>', textfield(-name=>'MGFld',-value=>$MasterGardener,-size=>30 +,-maxlength=>50,-id=>'MGFld', -class=>'DataIn', -readonly=>'readonly'), br, '<label for="CallBackMGFld">Call Back MG </label>', textfield(-name=>'CallBackMGFld',-value=>$MGCallBack,-size +=>30,-maxlength=>50,-id=>'CallBackMGFld', -class=>'DataIn', -readonly=>'readonly'), br, "<label for='FactSheetsFld'>Fact Sheets </label>", textfield(-name=>'FactSheetsFld',-value=>$FactSheets,-size +=>2,-maxlength=>2,-id=>'FactSheetsFld', -class=>'DataIn', -readonly=>'readonly'), br, "<label for='TopicFld'>Topic </label>", textfield(-name=>'TopicFld',-value=>$Topic,-size=>20,-maxl +ength=>30,-id=>'TopicFld', -class=>'DataIn', -readonly=>'readonly'); print start_form(-method=>"POST", -name=>"NextForm", -id=>"NextForm", -action=>"http://www.hortline.rbhyland.org/SearchConta +cts.cgi"); print br,submit(-name=>'Next',-value=>'Next'); print br,submit(-name=>'Prev',-value=>'Prev'); print end_form; } sub getIDs { $SrchStr = param('SearchFld'); $dbh = DBI->connect("DBI:mysql:database=hortline;host=mysql.hortli +ne.rbhyland.org","rbhyland","dh_R95w") or &dienice("Database logon failed: $DBI::errs +tr\n"); $selectstr = "SELECT * ". "FROM Contacts ". "WHERE County = ?; "; $sth = $dbh->prepare("$selectstr"); $sth->execute($County); while ( @row = $sth->fetchrow_array() ) { my $row = "@row"; if (index(uc($row),uc($SrchStr)) >=0) { push(@ContactIDList, $row[0]); } } warn "Data fetching terminated early by error: $DBI::errstr\n" if $DBI::err; print "@ContactIDList",br; } sub dienice { my ($msg) = @_; print "<b>$msg</b>"; exit; } sub dbdie { my ($errmsg) = "$DBI::errstr<br />"; &dienice($errmsg); }

Replies are listed 'Best First'.
Re: Global Variables Not Acting Global
by anonymized user 468275 (Curate) on Apr 21, 2011 at 11:55 UTC
    I could be wrong, but I get the strong impression that you are expecting the value of the variable to persist between http requests. CGI::Session contains methods for storing and retrieving data in such cases.

    One world, one people

      You're right, I was, foolishly, expecting that, but I don't know why. I knew that this was a stateless environment. Thanks for the tip about CGI::Session. I will check it out.
Re: Global Variables Not Acting Global
by Eliya (Vicar) on Apr 21, 2011 at 11:51 UTC

    Are you running the CGI program persistently (such as under mod_perl), or are you running it as a "normal" CGI program?  In the latter case, the process terminates after every HTTP request, and with it all variables' values are gone...

Re: Global Variables Not Acting Global
by bart (Canon) on Apr 21, 2011 at 11:10 UTC
    The value of $CurIDPtr only changes if param('Next') or param('Back') is set. Maybe neither is happening?

    And perhaps what you really want is to pass a parameter for that variable through the form, otherwise it'll always be 0, 1, or -1.

      Next and Prev are being set. I can add another parameter, but shouldn't a global variable be global? Does the if block override a global variable's value?
        No, in Perl a variable is global, anywhere, unless there's a my declaration in a surrounding block. I don't think variable scope is your problem.
        If both are set, of course the value is 0 again -- one of them takes care of increment, one of decrementing. Both add up to 0 in the end.
Re: Global Variables Not Acting Global
by moritz (Cardinal) on Apr 21, 2011 at 11:39 UTC
Re: Global Variables Not Acting Global
by LanX (Saint) on Apr 21, 2011 at 12:08 UTC
    What's your problem?

    Please demonstrate it in a condensed piece of code and plz make clear if your talking about one invocation of your CGI or persistent sessions.

    In the latter case (i.e. mod-perl, FCGI, ...), there are issues regarding package and lexical variables.

    Cheers Rolf

      I was expecting a global variable, $CurIDPtr, to maintain its value like a session variable. anonymized user 468275 put his finger on the problem.
        here a simple example of a persistent variable $count while using CGI::Fast

        use strict; use warnings; use CGI::Fast; our $count = 0; while ( my $q = new CGI::Fast ) { $count++; print $q->header( "text/plain" ), "You are request number $count. Have a good day!\n"; }

        (taken from O'Reilly's CGI book and modernized )

        Cheers Rolf