in reply to CGI: Passing variables to a subroutine

To much work!

use CGI; my $query = CGI->new(); if ($query->param( "button" ) eq 'first') { display_first( $query ) } else { display_second( $query ) } sub display_first { my $query = shift; # declare your variables here } sub display_second { my $query = shift; # declare your variables here }

There is no reason to declare all your variables when they are already in the $query object. Just pass the query object and in the routine assign values to the variables as you need them. No more, no less.

Replies are listed 'Best First'.
Re^2: CGI: Passing variables to a subroutine
by Anonymous Monk on Jan 05, 2007 at 01:41 UTC
    There is no reason to declare all your variables when they are already in the $query object.

    This generates a warning (uninitialized value in string eq) when button does not already exist in the $query object.

    my $query = CGI->new(); if ($query->param( "button" ) eq 'first') { display_first( $query ) }
    Declaring variables helps keep track of what input is expected and set default values when none exists:
    my $region = $query->param( "region" ) || 42; my $button = $query->param( "button" ) || ''; if ($button eq 'first') { # '' gives no warning
    This generates a different warning (uninitialized value in hash element):
    my $handler = $handlers{$query->param( "button" )};
Re^2: CGI: Passing variables to a subroutine
by stumbler (Acolyte) on Jan 04, 2007 at 21:52 UTC

    Thanks for the response

    If I have to pass other variables that are not a part of the $query object, I presume that I should be passing that to the subroutine.

    Please look at the modified code below:- Any suggestions?

    use CGI; my $query = CGI->new(); # get the data structure my $ref_data= create_data_structure(); if ($query->param( "button" ) eq 'first') { display_first( $query, $ref_data ) } else { display_second( $query, $ref_data ) } sub display_first { my ( $query, $s1_data ) = @_; # declare your variables here ... # use $s1_data to do something in this sub } sub display_second { my ( $query, $s2_data ) = @_; # declare your variables here ... # use $s2_data to do something in this sub } sub create_data { ... create a hash data structure ... ... return \%hash; }

      Use a dispatch handler.

      my %handlers = ( first => \&display_first, second => \&display_second, ... ); my $handler = $handlers{$query->param( "button" )}; if (!$handler) { ... } $handler->($query, $region, $var1, $var2, $var3);

      You might even want to make some of those variables global, especially if they aren't changed after being set. Alternatively, the handler could use $query to get the variables it needs.

      You don't actually need to pass $ref_data as an argument to your subroutines, because they're already in its lexical scope. (They can "see" it already.)

      But, it's good practice to keep the scope of things as small as possible, so why not just call create_data() in each of the subroutines where you need it? (Presumably, only one of them will be running per CGI request anyway.)

      And I second the suggestion of using a dispatch table. There's also CGI::Application, which is like a dispatch table on steroids with all sorts of nifty OO stuff and plugins.