Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

(CGI::Vars) Re: Variable Variables

by mwp (Hermit)
on Dec 05, 2000 at 07:41 UTC ( [id://44927] : note . print w/replies, xml ) Need Help??

in reply to Variable Variables

Doing something like this is bad practice, for a variety of reasons. Mostly because if someone adds a form field that you did not prepare for, it might affect a different part of the script. For example, if someone added a form field called "key" your script would die because it would try to set $key to the form value, which is also the loop iterator.

If you want to avoid calling $query->param() each and every time you want to access the form values, and I sympathize, you should try something like this:

use strict; use CGI; my $query = new CGI; # this will import the form values my %vars = $query->Vars(); # this will "export" the form values print "Name: ", $vars{name}, "\n"; cetera. See the manpage for more info about the Vars syntax.



Replies are listed 'Best First'.
Re: (CGI::Vars) Re: Variable Variables
by Kanji (Parson) on Dec 05, 2000 at 09:38 UTC
Re: (CGI::Vars) Re: Variable Variables
by Adam (Vicar) on Dec 05, 2000 at 07:50 UTC
    Actually, his code didn't have that particular flaw. He only creates the variables in his array. But your point is good, its something people need to think about.

    I also like the $query->Vars(); suggestion. never seen that before. cool :-)

      Thanks. Vars() is relatively new, around 2.50 if I remember correctly.

      I understand what you're saying... he only creates the variables in the list he defines for the foreach loop. I guess what I was trying to imply was that whomever edits the form and adds a field is going to have to come into the CGI script and modify that too, creating the situation I described. =) You would hope the programmer in question would realize their folly and change the formfield name so that it wouldn't break the script, but never forget O'Toole's postulate: Murphy was an optimist.

Re: (CGI::Vars) Re: Variable Variables
by repson (Chaplain) on Dec 05, 2000 at 08:15 UTC
    I recall seeing a link to a PHP(?) bug report because the automatic action in that language is to create variables in main namespace named after the form elements. However people could write over package globals that people didn't want changed, compromising security.
Re: (CGI::Vars) Re: Variable Variables
by Anonymous Monk on Dec 06, 2000 at 01:59 UTC
    This is OK unless a parameter is specified more than once as in '?ar=3&ar=2' - in this case Vars loses a value. The following is what I use:
    my %args = (); # get cgi parameters into a hash. preserve multi-valued # parms for my $p ( $cg->param() ) { my @tmp = $cg->param($p); if ( scalar @tmp == 1 ) { $args{$p} = $tmp[0] } else { $args{$p} = [ @tmp ] } }
    Now %args has your params, w/ multi-valued ones as references to arrays. - Bob Niederman
      That's a good point. (Neat routine, too.) But consider this:

      Before coming here, and before matured, I was a notorious advocate of As a matter of fact, part of the reason that the Vars method in was added was to facilitate the transition of users over to In you would do something like this:

      require ""; &ReadParse(*input); # store form values in the glob "input" print &PrintHeader; # print HTML header print "Name: ", $input{name}, "<br>\n";

      This was very nice syntax and worked well for me for many moons. =) When the form parser would encounter multiple values for a single field name, it would string them together with the NUL character (by default), so you could do this:

      print "First value: ", $input{valueList}, "<br>\n"; print "All values: ", join("<br>\n", split(/\0/, $input{valueList}));

      And it would do exactly what you'd expect it to do. Neat, huh? Well, conveniently enough, inherited this behaviour. But don't take my word for it:

      #!/usr/bin/perl -w # /~alakaboo/cgi-perl/ use strict; use CGI; my $q = new CGI; my %v = $q->Vars(); print $q->header('text/plain'); { local $" = "\n"; my @tmp = split /\0/, $v{ar}; print "@tmp"; }