Repackage Your Way to Success
May 15, 2000
Often the easiest solution to this problem is to separate your Perl
code into a package of its own. Typically you can do this by
breaking your Perl script into two parts. Below, we break the
example script we've seen into two files:
"name.cgi" and "name_lib.pl".
name.cgi
#!/usr/bin/perl -w
use strict;
use CGI;
require "/home/username/cgi-bin/name_lib.pl";
&name_main::init();
name_lib.pl
package name_main;
sub init {
my $cgiobj=new CGI;
print $cgiobj->header;
$name=$cgiobj->param("firstname").' '.
$cgiobj->param("lastname");
print &formatName($name);
sub formatName {
return uc($name);
}
}
1;
__END__
What we've done here is basically to encapsulate our code into a
library package, which we then pull-in via a require into
the mod_perl package space where name.cgi will be executed.
The name.cgi file, which is the file we call in a URL,
specifies which modules and libraries to pull in -- as you see,
this is where we've specified the strict and CGI
module, and where we pull in what is now our library, what was the
meat of this script, name_lib.pl. The main code of our script
has been wrapped inside a subroutine, init(), which is
called using the fully qualified name in name.cgi.
The strange notation at the end of the package with the number 1
and the __END__ token are needed to appease the Perl interpreter,
which wants to receive a true value when it pulls in the package.
If you leave these out the script won't work and an appropriate
reminder will be dropped into your Apache errorlog.
Looking at the code in name_lib.pl, you can see that we've
dropped the my() declaration from $name. Now it's as
if we've created the global variable we want -- and we have --
although it is only global within this package that we've named
name_main. Note that if we later decided to use $cgiobj
within a subroutine in this package, we would also have to drop its
my() declaration, otherwise the nested subroutine problem
would surface again.
This all certainly seems like a lot of acrobatics, but it solves
our problems: by placing most of the code within its own package,
we can create "global" variables within that package,
free from the nested subroutine problem with my() scoped
variables. Although this all may seem a bit confusing at first,
when you boil it all down, it works. The above name.cgi can
be reloaded and reloaded in your browser with different parameters
and it will never "remember" an earlier invocation.
My() Troubles
The Perl You Need to Know
Compilation Amnesia
|