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

I have a requirement where I need to take a URL string, split it, sort & url encode the constituents. I tried playing with URI->new() and $uri->query_form. But that evidently doesn't cope with repeated parameters.... e.g.
my $info = "/?foo=Zoo&foo=aha";
Only yields
$VAR1 = { 'foo' => 'aha' };
I can use Perl split on "?" to split the URL from the parameters, but then I'm at a loss how to proceed from there.... because I guess I can continue by spliting on "&" and "=", but then I run into the same issue of repeated parameters.

Replies are listed 'Best First'.
Re: Question about URL query strings
by kennethk (Abbot) on Feb 17, 2014 at 23:10 UTC
    You mistake is (almost assuredly) in assigning it to a hash. Rather than code that says:
    my %param = URI->new('/?foo=Zoo&foo=aha')->query_form;
    you should respect that you have multiple values associated with a given key, and use hashes of arrays (perllol, HASHES OF ARRAYS):
    my @list = URI->new('/?foo=Zoo&foo=aha')->query_form; my %param; while (@list) { push @{$param{shift @list}}, shift @list; }
    or something similar.

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: Question about URL query strings
by Your Mother (Archbishop) on Feb 17, 2014 at 23:02 UTC

    It works, so you're doing something squirrelly or flattening it accidentally. Show us teh codez!

    perl -MURI -MData::Dump=pp -le 'pp(URI->new("/?foo=Zoo&foo=aha")->quer +y_form)' ("foo", "Zoo", "foo", "aha")
      #!/usr/bin/perl use 5.014; use strict; use warnings; use autodie; use Data::Dumper; use URI; my $info = "/?foo=Zoo&foo=aha"; my $uri = URI->new($info); my %query = $uri->query_form; print Dumper \%query;
Re: Question about URL query strings
by tangent (Parson) on Feb 17, 2014 at 23:37 UTC
    You could use URI::QueryParam which has the query_param() method that works just like CGI's param() method:
    use URI; use URI::QueryParam; my $info = "/?foo=Zoo&foo=aha"; my $uri = URI->new($info); my %params; for my $name ($uri->query_param) { my @values = $uri->query_param($name); $params{$name} = @values > 1 ? \@values : $values[0]; }
Re: Question about URL query strings
by thomas895 (Deacon) on Feb 20, 2014 at 05:05 UTC

    Another module that works for this task is actually CGI(::Simple).
    Use it like so:

    use strict; use warnings; use Data::Dumper qw(Dumper); use CGI; #or CGI::Simple, if you prefer my $info = "/?foo=Zoo&foo=aha"; my $q = CGI->new((split /\?/, $info)[1]); #again, replace with CGI::Si +mple if desired #and now... my @foos = $q->param("foo"); #or my %params = map { $_ => [ $q->param($_) ] } $q->param(); print Dumper \%params; __END__ $VAR1 = { 'foo' => [ 'Zoo', 'aha' ] };

    Not everybody likes this approach, especially the zealots who believe CGI is a thing of the past and should be banished, and those who use it be crucified. Take into account your own standards and/or those of your boss/organization/etc.

    ~Thomas~ 
    "Excuse me for butting in, but I'm interrupt-driven..."