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

I am seeking wisdom on how one would go about defining global variables for a cgi application that get their values from a database. These variables will change periodically (whenever the database values change) and they are used throughout an entire application.

The problem I am running into is that if I wait until a run mode to grab the data from the db then I must declare the global variables without a value at the top of the program. The data will usually be there for the first run mode but by the time we goto the second (or a different) run mode, then the data is blanked out again because of the global declarations with no value.

I have been able to call a seperate function below the setup function and manually define these global variables here, but I have been unsuccessful on calling it up with $self to attach to the db handle. If I could get this to work then it would probably be golden.

Thanks for any advice/help.

minimal code sample:
############################ our variable1 = 2003; our variable2 = 2004; sub setup{ my $self=shift; $self->start_mode('start'); $self->mode_param('rm'); my $dbh=getDbConnection("universe"); $self->param('dbh'=>$dbh); $self->run_modes( start=>\&showstart, search=>\&genSearchPage, show_type_1=>\&genShow1, show_type_2=>\&genShow2, calculate=>\&genCalculator, iamge=>\&generateImage ) } sub showstart { use variable1 here; use variable2 here; } sub genSearchPage { use variable1 here; use variable2 here; } sub genShow1 { use variable1 here; use variable2 here; } ... etc. etc.
#########################

As you can see, right now the variable1 and variable2 are hard coded, but I want to be able to get their values from a database and then have all the subs be able to access those variables with the values from the database. Problem is that I dont connect to the database until I am in setup, so unless I manually connect again to the database at the top, I cant get a connection to the db before I run setup.

Edited by footpad, 19 December 2003: Revised HTML formatting and added <code> tags.

Replies are listed 'Best First'.
Re: CGI Application and global variables (from a database)
by jdtoronto (Prior) on Dec 19, 2003 at 17:02 UTC
    I assume you are using CGI::Application? If you are then it is pretty darned easy.

    Generally you are going to connect to the database in the setup subroutine and you set the param $self->param('mydbh' => DBI->connect('DBI:mysql:appname', 'xxxxx', 'xxxxx')); then in the cgiapp_prerun I do a variety of things including validating sessions and requiring logins etc. You can get the database handle and then set up more global values here, he is a simple cgiapp_prerun I am using right now:

    sub cgiapp_prerun { # If user has a session ID then validate it, otherwise get them on +e my $self = shift; my $dbh = $self->param('mydbh'); my $q = $self->query(); my $session_h = new CGI::Session("driver:MySQL", $q, {Handle => $d +bh}); $self->param('up_session' => $session_h); }
    Does that help?

    jdtoronto

      Rock on JD!

      This is *EXACTLY* what I needed.
      Major KUDOS go out to you.
      I just started learning about CGI::Application the past month or two. I am still at the beginning stages and did not see any mention of the cgiapp_prerun in the documentation on CPAN.
      Thanks a bunch!
Re: CGI Application and global variables (from a database)
by davido (Cardinal) on Dec 19, 2003 at 16:54 UTC
    It sounds like you're expecting a CGI script to stay resident between CGI requests. Are you talking in terms of mod_perl perhaps?

    And $self... is that a Perl object's internal self-reference, or some other sort of $self?

    The devil is in the details. I think we're going to need to have a look at what sort of devil we're dealing with.


    Dave

Re: CGI Application and global variables (from a database)
by Joost (Canon) on Dec 19, 2003 at 16:46 UTC
    Please show some code, because I can't figure out what you are actually trying to do.

    Please note CGI programs run once for every request and then exit, which means that all variables will be uninitialized unless you set them, even if you set them some time ago for another request.

    Also, how is your program supposed to know when the value in the database has changed without querying the datase first? You might as well just get the data from the DB for every request.

    Joost.

Re: CGI Application and global variables (from a database)
by freddo411 (Chaplain) on Dec 19, 2003 at 18:20 UTC
    Great Question.

    First off, you'll probably be lynched for using globals, but they are quite handy in some circumstances. I use them. I read mine out of a configuration file, but getting them out of a DB is conceptually the same.

    In my case I'm using CGI:App with CGI's so keep in mind this is executed for each 'hit' from the browser. If I was in a high volume environment, I'd be looking at mod_perl. Anyway, I took the following approach to solve the same problem:

    I declared a base class that extended CGI::App

    package MyCGIApp; use CGI::Application::ValidateRM; use strict; use vars qw( $VERSION); $VERSION = 1.00; use base qw(CGI::Application); sub cgiapp_init { my $self = shift; ####################### package G; use Config::General; use vars qw( %CF ); %G::CF = ParseConfig("../mymodules/config.dat"); ... more stuff would be here (perhaps connecting to the DB) ... } # end MyCGIApp.pm

    Meanwhile in another file / perl module I extend from MyCGIApp, inheriting stuff including the variables. I use the package qualified name of the "global" variable (conviently called "G") so that strict won't complain.

    #!/usr/local/bin/perl package CDNR; use base MyCGIApp; # Extending the class ... runmodes, etc, etc, ... in one of them: $t->param( 'Header' => "My Header", 'HeaderText' => "$G::CF{headertext}", );

    In my example above, I've put all my globals into a hash, but you could use a scalar or two if you liked. That's it. Works like a charm.

    BTW, speaking to the estimeed Monks around here; what is your opinion of my particular use of inheritence in this case?

    Cheers,

    -------------------------------------
    Nothing is too wonderful to be true
    -- Michael Faraday

Re: CGI Application and global variables (from a database)
by mpeppler (Vicar) on Dec 19, 2003 at 16:46 UTC
    How about posting a minimal code example that shows what you are trying to do?

    Michael

Re: CGI Application and global variables (from a database)
by swngnmonk (Pilgrim) on Dec 19, 2003 at 18:00 UTC

    Ignoring the specific details, I have a more general concern - it seems like you want a DWIM (do what I mean) kind of solution. You want your CGI to cache values from a DB, so that you don't need to go & retrieve them every time, yet the data from the DB may change at what seems to be arbitrary times.

    As we've seen in the above posts, there are a number of ways to keep this data resident in the live CGI without hitting the DB, but how do you plan to handle updates? When does the CGI know to query the DB for the new information? Is this information that should really be in a database? Perhaps this is something that should be in a config file that's read on startup?

    There's nothing wrong with trying to minimize the amount of DB activity - in fact there's a lot right with that concern. That being said, DB handles can be cached and simple queries in a well-configure DB return fast. Don't create a new problem to solve one that might not be a big issue.