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

Okay, I'm have a *teensy* problem with CGI.pm

If I make a CGI object: $query I can get the parameter (or cookie) value by calling

$a=$query->param('key'); (or $a=$query->cookie('key');)

if the parameter is an array I can do

@a = $query->param('key');

kinda cool. *BUT* if I want to do something like

foreach $key ($query->param){
... something with $query->param($key) ...
}

$query->param($key) may or may not be an array. How can I know which?

===
well chromatic had the only real solution although it seems pretty inelegent. I guess I didn't make myself clear. When I said how do "I" know, I meant how can my program know, or more accurately how can I program generically. The "foreach" was not to go through the values of a $query->param('key') but to go through all parameters most of which are scalar values but a few of which are lists.

Basically, what I want is something like this:

foreach $key ($query->param){
@a or $a = $query->param($key) depending on whether or not $query->param($key) is a list or a single value
}

I can do

foreach $ ($query->param){ @a = $query->param($key); if (@a > 1){ $a = $query->param($key) } }
but that just seems so ... inelegent.

===

Update to an update: Actually what I really wanted to do was:

$condition{$key} = \@{$query->param($key)} || $condition{$key} = $query->param($key);

but that doesn't work.

  • Comment on CGI.pm: $q->param can be an array. Can be a single value. How do you know which?
  • Download Code

Replies are listed 'Best First'.
Re: CGI.pm: $q->param can be an array. Can be a single value. How do you know which?
by chromatic (Archbishop) on Apr 10, 2004 at 18:44 UTC

    Presumably you know what you expect; if you have a first_name parameter, fetch the value in scalar context.

    If you do need a truly generic solution, always call param() in list context; stuff the values into an array and check the number of elements of the array. If it's one, you have one value. If it's more than one, you have a list of values.

Re: CGI.pm: $q->param can be an array. Can be a single value. How do you know which?
by revdiablo (Prior) on Apr 10, 2004 at 19:20 UTC

    First, an issue of terminology. param() doesn't return an array, it returns a list. Secondly, using foreach with only one element is perfectly fine. It will simply loop once. You could use this as a generic (as chromatic mentioned) way to handle your CGI parameters, but I repeat his advice that you should probably only look for a list when you expect a list.

Re: CGI.pm: $q->param can be an array. Can be a single value. How do you know which?
by tachyon (Chancellor) on Apr 11, 2004 at 01:06 UTC

    Both CGI and CGI::Simple store the param values internally as:

    { key => [ val ], key2=> [ val1, val2, ... ] }

    So the values are really always 'arrays' (well array refs) but if there is one val it is a single element array.

    The param method is sensitive to context via wantarray so if you call it in list context you get all the values, but in scalar context you get val->[0]. The || operator forces scalar context which is why your syntax does not work.

    The easy way to do it is just assume you have a list, and loop through it. Looping through a list of one is quick ;-)

    cheers

    tachyon

Re: CGI.pm: $q->param can be an array. Can be a single value. How do you know which?
by Anonymous Monk on Apr 10, 2004 at 19:04 UTC
    [me@here perl]$ cat foo.pl #!/usr/bin/perl -l use CGI qw(param); print for param('foo'); [me@here perl]$ ./foo.pl 'foo=bar' bar [me@here perl]$ ./foo.pl 'foo=bar&foo=baz&foo=qux' bar baz qux
Re: CGI.pm: $q->param can be an array. Can be a single value. How do you know which?
by davorg (Chancellor) on Apr 11, 2004 at 06:33 UTC

    One small point of terminology, "param" _never_ returns an array. It returns a list. The difference can be important.

    Here's some code that does what (I think) you want.

    my %params; foreach (param) { $params{$_} = [ param($_) ]; $params{$_} = $params{$_}[0] if @{$params{$_}} == 1; }

    You'll end up with a hash (%params) that contains a key/value pair for each parameter name. If the parameter is single-valued the value will contain that (single) value. If the parameter is multi-valued, then the value will be a reference to an anonymous array containing all of the values.

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: CGI.pm: $q->param can be an array. Can be a single value. How do you know which?
by Anonymous Monk on Apr 10, 2004 at 19:34 UTC
    use strict; use CGI::Simple qw(-debug2); my $q = CGI::Simple->new(); for my $key ( $q->param() ) { # this: for my $value ( $q->param($key) ) { printf "'%s' has value '%s'\n", $key, $value; } # or this: print "'$key' has value(s):\n", map { "- $_\n" } $q->param($key); }
Re: CGI.pm: $q->param can be an array. Can be a single value. How do you know which?
by cLive ;-) (Prior) on Apr 11, 2004 at 08:34 UTC
    :)
    my %condition=(); foreach my $key ( $q->param() ) { local @_; $condition{$key} = ( @_ = $q->param($key) ) - 1 ? \@_ : pop; }
    cLive ;-)
Re: CGI.pm: $q->param can be an array. Can be a single value. How do you know which?
by Joost (Canon) on Apr 11, 2004 at 08:53 UTC