http://qs321.pair.com?node_id=581702

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

Hello Monks,

I am a little confused as to how to handle common subroutines that are used by multiple CGI scripts. Looking at this node , I understand that there are different ways to handle this.

I have basically followed the last suggested approach (i.e. having all the common routines in a separate module called as 'common.pm' and then call it in the scripts I need.)

Here is the skeleton for the common.pm module...

package common; use strict; use Exporter; use CGI qw/:standard :delete_all :escapeHTML :html3 :all/; # Setup to export common subroutines and variables used by many script +s our ( @ISA, @EXPORT_OK, $q ); @ISA = qw( Exporter ); @EXPORT_OK = qw( $query is_tainted check_user authenticate set_path print_header print_footer error_form log_msg ); # Instantiate a new CGI object $query = CGI->new; sub check_user { .... } sub is_tainted { .... } sub authenticate { .... } sub set_path { .... } sub print_header { .... } sub print_footer { .... } sub error_form { .... } sub log_msg { .... } 1;
and here is the sample script in which I use the module
use strict; use lib "/path/to/lib"; use common qw( $query is_tainted check_user authenticate set_path print_header print_footer error_form log_msg ); # Create query objects to retrieve input my $username = $query->param( "user" ); # Display error message if the query objects are not found unless ( defined $username ) { error_form( "<msg to display>" ); exit; } # Set path my $dir_path = set_path( $username ); # Check if $dir_path is set correctly if ( $dir_path eq "Error" ) { error_form( "Error setting path" ); exit; } # Authenticate my $valid_code = authenticate( $username); if ( $valid_code eq "FALSE" ) { log_msg( <messages> ); error_form( "Invalid code" ); exit; } #print the html page print $query->header(); print $query->start_html(-title => 'Welcome', -bgcolor => 'white', ); print_header( "Welcome" ); print $query->start_form( -name => 'data', -action => 'page2' ); print $query->hidden( -name => "user", -value => $username ); ... etc.. ... print $query->end_form(); print $query->table( { -border=>0}, $query->Tr( [ $query->td( [ $query->a( {-href=>"j +avascript:submitform()"}, $query->img({-align=>"center", -sr +c=>"submit.gif ", -border=>0 })) ]), ] ), ); print_footer(); print $query->end_html(); log_msg( <arguments> );

First, Is this a fairly good approach? or is it better to create individual perl scripts for each subroutine (similar to 'C')

Second, as you can see in the sample script, the code until '#print the html page' is more likely to be common across many cgi scripts. Can I make that portion as another subroutine and use it in all the scripts?

Please share your comments.

Replies are listed 'Best First'.
Re: Converting common subroutines as a module
by Fletch (Bishop) on Nov 01, 2006 at 16:42 UTC
    • Lower case'd module names (e.g. "common") are reserved for Perl's internal use by convention.
    • It'd be better to create the CGI instance in the main body and pass that as an argument to your utility routines
    • You might consider using one of the frameworks like CGI::Application which provides functionality similar to this off-the-shelf
      I second the CGI::Application recommendation. Through the website I linked to, you can find a list of a lot of plugins that are available, including some to Authentication and Authorization.

      I've been using this framework for years and have found it very helpful, and appropriate for all scales of projects.

        Thanks for the response. I will definitely look into CGI::Application for my website.

        I forgot to mention about an important aspect of my application. After authentication and path set-up, I also have some pages with non-cgi perl scripts( like reading data files to create data structures to be used in defining the UI). Presently, I have them as apart of the cgi script. Can I handle that portion as well using CGI::Application?

Re: Converting common subroutines as a module
by Zaxo (Archbishop) on Nov 01, 2006 at 19:04 UTC

    Since your subs all seem to take a CGI instance as an argument, you could subclass CGI.pm as Site::CGI and use that instead of CGI.pm in the top level scripts. That would help prevent putting functions with dissimilar purposes in your Common.pm.

    The subclassing mechanism is not too difficult. The basic steps are:

    package Site::CGI; use CGI; @ISA = qw/CGI/; # subroutine definitions, object instance is first arg # . . . 1;
    Save that file as Site/CGI.pm somewhere in your @INC path.

    You would then, in top level scripts, say,

    use Site::CGI; # instead of use CGI; my $query = Site::CGI->new; # . . . print $query->my_sub; # etc

    After Compline,
    Zaxo