apprentice, I understand your reasoning, but this is an excellenent example of why you don't want to use global variables. You may want to read about good programming practices and how you can get bit violating them.
The larger an application grows, the more items tend to need access to global variables. While I realize that you don't want to pass around a bunch of different objects and variables, it's very, very easy to lose track of where you're instantiating them, changing them, etc. However, if code is written tightly enough, I find that there's less passing around of these objects than one would think. Usually, you're passing the data gotten from the objects than the objects themselves.
What would be the best way for you to approach this would vary greatly upon your application needs. I don't know what you're use you're putting your CGI objects to, for example. Let's say, for example, that you're only using the CGI object for the CGI::param() method. You could package all of your objects into an "application" object and just pass that around instead of all of the objects and data. What follows is a much different solution from what others suggest and I'm not wild about it, but I though I would toss it out there in the spirit of TIMTOWTDI.
package My::Application;
use strict;
use DBI;
use CGI;
sub new {
my $class = shift;
my $q = CGI->new;
my %data = map { $_, [ $q->param($_) ] } $q->param;
my $href = {
_dbh = connect_routine(),
_data = \%data
};
bless $href, $class;
}
sub form_data {
# remember that all data returned from this is tainted!!!!
my ( $self, $item ) = @_;
if ( ! exists $self->{ _data }{ $item } ) {
return undef;
} elsif ( wantarray ) {
return @{ $self->{ _data }{ $item } };
} else {
return $self->{ _data }{ $item }[0];
}
}
sub get_user_info {
my ( $self, $id ) = @_;
# Note the placeholder .. greater security
my $sql = "SELECT first, last FROM users WHERE id = ?";
my $sth = $self->{ _dbh }->prepare( $sql );
my $rc = $sth->execute( $id );
.
.
.
}
I think you get the idea from the above (very untested) example. With that, you encapsulate all application specific objects and data into one object and just pass that around. The objection I have to my method is that now you're mixing cheese and Wednesday. Frankly, I don't like the idea of mixing form-handling code and database code in one object, but this is just a rough idea to show you how it's done. On the other hand, if you reframe it with the idea that you're gathering all application specific data retrieval into one module, then I think it's justifiable.
use strict;
use My::Application;
my $app = My::Application->new;
# it's transparent to the programmer, but this is getting
# the data from the submitted form data
my $user_id = $app->form_data( 'user_id' );
# again, we have application specific data, but from
# the database instead of the user form
my $user_details = $app->get_user_info( $user );
Cheers,
Ovid
Vote for paco!
Join the Perlmonks Setiathome Group or just click on the the link and check out our stats. |