Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

CGI::Application - alternative to using $self->param?

by isync (Hermit)
on Nov 20, 2007 at 23:25 UTC ( [id://652022]=perlquestion: print w/replies, xml ) Need Help??

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

Is there an alternative to using the $self->param() function of CGI::Application to access an application-wide data structure, while still staying true to the CGI::Application paradigm?

In my homebrewn script before C::A, I used a global %hash. Back then I could access my %hash in print contexts or similar like this
print "this funky var: $hash->{funky}";
Doing the same with the param() function does not work, as it is a subroutine reference and not a var:
print "this funky var: $self->param('funky')";
Also declaring values with param is sometimes tedious:
$self->param('key') = \%valuehash
(which gives an lvalue error...)

As I think, there are two ways of solving this:
1. declaring my %hash as our at the start of MyApp.pm -or-
2. pulling the $self->param() values into scope at the entry of each runmode subroutine
sub somerunmode { my $value1 = $self->param('key1'); my $value2 = $self->param('key2'); ... }

Both ways seem to be a deroute from the CGI::Application approach. Some feedback on best practice here is very welcome! (Would loosening my use strict; pragma make life easier?)

BTW: sorry for this being not-exactly-perl-related..

Replies are listed 'Best First'.
Re: CGI::Application - alternative to using $self->param?
by polettix (Vicar) on Nov 21, 2007 at 01:12 UTC
    The CGI::Application way lets you attach data to the object instead of putting it as a global somewhere. This lets you forget *where* you put the data, i.e. in which particular package, and could minimise interactions with other pieces of software.

    Elaborating on friedo's suggestion, why don't you simply set the hash as a parameter:

    $self->param(hash => { funky => 'Brown' });
    somewhere in the beginning, and then retrieve and use it:
    sub some_runmode { my $self = shift; my $hash = $self->param('hash'); print "this funky var: $hash->{funky}"; }
    like you did before?

    Flavio
    perl -ple'$_=reverse' <<<ti.xittelop@oivalf

    Io ho capito... ma tu che hai detto?
Re: CGI::Application - alternative to using $self->param?
by pc88mxer (Vicar) on Nov 21, 2007 at 00:06 UTC
    After you create the C::A instance, you can always stick it in a global variable:
    my $cgi = new CGI::Applicaton(...); $::global_var = $cgi; ... use $::global_var now anywhere ...

    A variable like $::global_var is a fully-qualified name which is as close as Perl gets to global variables. It is equivalent to $main::global_var or to using our in package main:

    ... { package main; our $global_var; # same as $::global_var and $main::global_var ... }

    You can create a tie interface if you want to access parameters like you did with a hash. See man perltie for more details. However, if you are writing new CGI applications, I wouldn't do this. Just extract parameters into simple variables if you need to use them more than once. A tie interface would allow you to use hash-like syntax for the following operations:

    print $hash{'key'} # same as print $webapp->param('key') $hash{'key'} = 3; # same as $webapp->param('key', 3);
    However, I would make sure it is really worth implementing because it will add complexity and degrade your application performance.

    If you really need to access the values as a hash, perhaps you can first extract all the CGI parameters to a hash like this:

    our %hash; my @all_params = $webapp->param(); for my $p (@all_params) { $hash{$p} = $webapp->param($p); # } ... use %hash instead of calling $webapp->param(...) ...
      Also, the ->param(...) method is read-only - you can't change values of parameters with it.

      Sure you can. It works pretty much just like CGI's param method. This works fine:

      $self->param( key => \%valuahash );

      If you want a hash with all your params, you can get it like this:

      sub some_run_mode { my $self = shift; # note that CGI.pm does the same thing: my @params = $self->param; my %hash = map { $_ => $self->param( $_ ) } @params; }

      That would be a little tedious to do in every runmode, but you could do it in a prerun hook instead.

        Thanks for pointing that out. Shortly after writing that I decided to check it out and re-edited my response accordingly.
Re: CGI::Application - alternative to using $self->param?
by saberworks (Curate) on Nov 21, 2007 at 04:10 UTC
    I recommend extending CGI::Application with another class and making all your CGI::Application classes inherit from your new base class instead of CGI::Application directly. You can then define your own set of methods (or just a single one) that can be a bit more clear. For example, you can initialize your %hash there and then make your own accessor, hash(). That way, you don't have to use "param" with everything (which can be vulnerable to typos in the keys you pass it). For example, if you call:

    my $hashref = $app->param('hush');

    And param "hush" isn't defined, what happens? If you make a method to get it:

    my $hashref = $app->hash();

    If you misspell the hash() method call, you will get a real perl error.
Re: CGI::Application - alternative to using $self->param?
by nedals (Deacon) on Nov 21, 2007 at 07:33 UTC
    I'm not sure how important interpolation is to you.
    One relatively simple solution...
    print 'this funky var: '.$self->param('funky');
Re: CGI::Application - alternative to using $self->param?
by isync (Hermit) on Nov 21, 2007 at 10:34 UTC
    Thanks everyone for these numerous approaches!

    As it seems the our approach is not that bad. Nevertheless, the more CGI::Application-way of doing it seems to be to declare my %hash and then stuff a ref to it into $self->param('hashref'); consequently pulling the ref/the hash into scope at the entry of each runmode subroutine with my $hashref = $self->param('hashref');

    I will see if I will migrate away from the current global approach. Further hacking on my script may lead there.. Again, thanks everyone!
Re: CGI::Application - alternative to using $self->param?
by trwww (Priest) on Nov 21, 2007 at 21:17 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://652022]
Approved by friedo
Front-paged by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (1)
As of 2024-07-23 02:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.