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

Greeting and thanks in advance. I have a cgi script that I where I would like to define a hash as follows:

$cgi = new CGI; ... do stuff ... my %data; = ( 'email'=>$cgi->param('user_email'), 'name'=>$cgi->param('user_name'), 'cell_phone'=>$cgi->param('user_cell_phone'), 'home_phone'=>$cgi->param('user_home_phone'), 'work_phone'=>$cgi->param('user_work_phone'), );
This works as expected except where $cgi_query->param() returns undef, then a key's value becomes the subsequent key. (IE: If, in this case, $cgi->param('user_email') was returning undef, then $data{'email'} would have a value of 'name'). Can anyone explain this and/or suggest a better method?

Thanks again,

pearte

Replies are listed 'Best First'.
Re: Unexpected Hash Assignment using cgi->params
by Errto (Vicar) on Nov 29, 2005 at 06:04 UTC
    What's happening is that param() isn't actually returning undef - it's returning an empty list. As it says in the documentation for CGI:
    If the parameter does not exist at all, then param() will return undef in a scalar context, and the empty list in a list context.
    So your keys and values get offset by one. Try this little example for an illustration of the effect of this:
    my %hash = ( foo => 1, bar => 2, baz => (), qux => 3); print keys %hash;
    What this means for you is that you need to call the param() method in scalar context. You can either do it directly:
    my %data = ( 'email'=>scalar $cgi->param('user_email'), 'name'=>scalar $cgi->param('user_name'), 'cell_phone'=>scalar $cgi->param('user_cell_phone'), 'home_phone'=>scalar $cgi->param('user_home_phone'), 'work_phone'=>scalar $cgi->param('user_work_phone'), );
    or you can try to get clever by doing something like this:
    my %data = ('email' => 'user_email', 'name' => 'user_name', 'cell_phone' => 'user_cell_phone', 'home_phone' => 'user_h +ome_phone', 'work_phone' => 'user_work_phone'); $_ = $cgi->param($_) for values %data;
    This takes advantage of the fact that you can modify hash values in place. Also, the scalar context is automatic because it's an assignment to a scalar value, so you don't need to specify it.
Re: Unexpected Hash Assignment using cgi->params
by kulls (Hermit) on Nov 29, 2005 at 06:15 UTC
    yes.
    In this case  $cgi->param('user_email') returns empty and $cgi->param read the hash-value as a pair. Also it makes  'work_phone' as an undef value eventhough it's valid.
    so u should undef the value if it's empty. like
    my %data; = ( 'email'=>$cgi->param('user_email') || undef, 'name'=>$cgi->param('user_name') || undef, 'cell_phone'=>$cgi->param('user_cell_phone') || undef, 'home_phone'=>$cgi->param('user_home_phone') || undef, 'work_phone'=>$cgi->param('user_work_phone')|| undef , );

    It's shows the exact result for me.
    -kulls
Re: Unexpected Hash Assignment using cgi->params
by Zaxo (Archbishop) on Nov 29, 2005 at 06:23 UTC

    In list context, when the key isn't present, the param method returns an empty list rather than undef. Put the param calls in scalar context and all will be well:

    use CGI; my $cgi = CGI->new( user_name => 'foobat' ); my %data = ( email => scalar( $cgi->param('user_email')), name => scalar( $cgi->param('user_name')) ); print "@{[keys %data]}\n"; __END__ email name
    Can you save yourself some work by looping over the params list and deriving your key names by substr or substitution?

    After Compline,
    Zaxo