Introduction to mod_perl (part 4): Perl Basics - Using Non-Hardcoded Configuration Module Names (
Page 6 of 9 )
You have just seen how to use a configuration module for configuration
centralization and an easy access to the information stored in this
module. However, there is somewhat of a chicken-and-egg problem--how
to let your other modules know the name of this file? Hardcoding the
name is brittle--if you have only a single project it should be fine,
but if you have more projects which use different configurations and
you will want to reuse their code you will have to find all instances
of the hardcoded name and replace it.
Another solution could be to have the same name for a configuration
module, like My::Config but putting a different copy of it into
different locations. But this won't work under mod_perl because of the
namespace collision. You cannot load different modules which uses the
same name, only the first one will be loaded.
Luckily, there is another solution which allows us to stay flexible.
PerlSetVar comes to rescue. Just like with environment variables,
you can set server's global Perl variables which can be retrieved from
any module and script. Those statements are placed into the
httpd.conf file. For example
PerlSetVar FooBaseDir /home/httpd/foo
PerlSetVar FooConfigModule Foo::Config
Now I require() the file where the above configuration will be used.
PerlRequire /home/httpd/perl/startup.pl
In the startup.pl I might have the following code:
# retrieve the configuration module path
use Apache:
my $s = Apache->server;
my $base_dir = $s->dir_config('FooBaseDir') || '';
my $config_module = $s->dir_config('FooConfigModule') || '';
die "FooBaseDir and FooConfigModule aren't set in httpd.conf"
unless $base_dir and $config_module;
# build the real path to the config module
my $path = "$base_dir/$config_module";
$path =~ s|::|/|;
$path .= ".pm";
# I have something like "/home/httpd/foo/Foo/Config.pm"
# now I can pull in the configuration module
require $path;
Now I know the module name and it's loaded, so for example if I need
to use some variables stored in this module to open a database
connection, I will do:
Apache::DBI->connect_on_init
("DBI:mysql:${$config_module.'::DB_NAME'}::${$config_module.'::SERVER'}",
${$config_module.'::USER'},
${$config_module.'::USER_PASSWD'},
{
PrintError => 1, # warn() on errors
RaiseError => 0, # don't die on error
AutoCommit => 1, # commit executes immediately
}
);
Where variable like:
${$config_module.'::USER'}
In my example are really:
$Foo::Config::USER
If you want to access these variable from within your code at the run
time, instead accessing to the server object $c, use the request
object $r:
my $r = shift;
my $base_dir = $r->dir_config('FooBaseDir') || '';
my $config_module = $r->dir_config('FooConfigModule') || '';