How to parse urlencoded query string into an array in PHP (without changing the name)

I know what you are thinking. "I can answer that question so quickly! It's a feature parse_str

!" But I have a little twist for you.

You see, PHP converts all request data names to valid PHP variable names. What kind? Even if they are not stored as variables? Where is this documented? This is not true.

$payload = 'data.name=value&data.other=value2';
parse_str($payload, $values);
var_export($values);
// Outputs:  array('data_name' => 'value', 'data_other' => 'value2')
// Expected: array('data.name' => 'value', 'data.other' => 'value2')

      

How can I parse the query string without this?

+3


source to share


2 answers


You can avoid renaming PHP parameter names by parsing the query string yourself. Split the string into characters &

and =

and then urldecode()

each part:

<?php

  $payload = 'data.name=value&data.other=value2';

  $values = array();

  $nv_strings = explode ('&', $payload);
  foreach ($nv_strings as $s) {
    $nv = explode ('=', $s, 2);
    $name = urldecode ($nv[0]);
    $value = (isset ($nv[1]) ? urldecode ($nv[1]) : null);
    $values[$name] = $value;
  }

  print_r ($values);

//  Array
//  (
//      [data.name] => value
//      [data.other] => value2
//  )

      




If the query string contains duplicate keys, the above code will overwrite the previous keys. This can also be solved:

<?php

  $payload = 'key=val1&key=val2&key=val3';

  $values = array();

  $nv_strings = explode ('&', $payload);
  foreach ($nv_strings as $s) {
    $nv = explode ('=', $s, 2);
    $name = urldecode ($nv[0]);
    $value = (isset ($nv[1]) ? urldecode ($nv[1]) : null);
    $values[] = array ($name => $value);
  }

  print_r ($values);

//  Array
//  (
//      [0] => Array ([key] => val1)
//      [1] => Array ([key] => val2)
//      [2] => Array ([key] => val3)
//  )

      




You might want to concatenate duplicate keys into subarrays:

<?php

  $payload = 'key1=val1&key1=val2&key2=val3';

  $values = array();

  $nv_strings = explode ('&', $payload);
  foreach ($nv_strings as $s) {
    $nv = explode ('=', $s, 2);
    $name = urldecode ($nv[0]);
    $value = (isset ($nv[1]) ? urldecode ($nv[1]) : null);
    if (isset ($values[$name])) {
      if (is_array ($values[$name])) {
        $values[$name][] = $value;
      } else {
        $values[$name] = array ($values[$name], $value);
      }
    } else {
      $values[$name] = $value;
    }
  }

  print_r ($values);

//  Array
//  (
//      [key1] => Array ([0] => val1
//                       [1] => val2)
//      [key2] => val3
//  )

      




You can simplify the code a bit by always using subarrays:

<?php

  $payload = 'key1=val1&key1=val2&key2=val3';

  $values = array();

  $nv_strings = explode ('&', $payload);
  foreach ($nv_strings as $s) {
    $nv = explode ('=', $s, 2);
    $name = urldecode ($nv[0]);
    $value = (isset ($nv[1]) ? urldecode ($nv[1]) : null);
    if (isset ($values[$name])) {
      $values[$name][] = $value;
    } else {
      $values[$name] = array ($value);
    }
  }

  print_r ($values);

//  Array
//  (
//      [key1] => Array ([0] => val1
//                       [1] => val2)
//      [key2] => Array ([0] => val3)
//  )

      

+2


source


This is fully documented in the PHP documentation for the function. parse_str

If the output does not work for your specific use case, you must use another function, or create your own. The key point here is that this function parses the string into variables.

parse_str - Parses the string into Parses str variables as if it were a query string passed through a URL and sets the variables in the current scope.



To parse the string you provided, this will work:

$payload = 'data.name=value';
$map = array();
$vals = preg_split('/=/', $payload);
$i= 0;
while($i < count($vals)) {
  $map[$vals[$i]] = $vals[++$i];
  $i++;
}

var_dump($map);

      

0


source







All Articles