- 
      
- 
        Save rubo77/6821632 to your computer and use it in GitHub Desktop. 
| <?php | |
| /** | |
| * do the same than parse_str without max_input_vars limitation: | |
| * Parses $string as if it were the query string passed via a URL and sets variables in the current scope. | |
| * @param $string array string to parse (not altered like in the original parse_str(), use the second parameter!) | |
| * @param $result array If the second parameter is present, variables are stored in this variable as array elements | |
| * @return bool true or false if $string is an empty string | |
| * | |
| * @author rubo77 at https://gist.github.com/rubo77/6821632 | |
| **/ | |
| function my_parse_str($string, &$result) { | |
| if($string==='') return false; | |
| $result = array(); | |
| // find the pairs "name=value" | |
| $pairs = explode('&', $string); | |
| foreach ($pairs as $pair) { | |
| // use the original parse_str() on each element | |
| parse_str($pair, $params); | |
| $k=key($params); | |
| if(!isset($result[$k])) $result+=$params; | |
| else $result[$k] = array_merge_recursive_distinct($result[$k], $params[$k]); | |
| } | |
| return true; | |
| } | |
| // better recursive array merge function listed on the array_merge_recursive PHP page in the comments | |
| function array_merge_recursive_distinct ( array &$array1, array &$array2 ){ | |
| $merged = $array1; | |
| foreach ( $array2 as $key => &$value ) { | |
| if ( is_array ( $value ) && isset ( $merged [$key] ) && is_array ( $merged [$key] ) ){ | |
| $merged [$key] = array_merge_recursive_distinct ( $merged [$key], $value ); | |
| } else { | |
| $merged [$key] = $value; | |
| } | |
| } | |
| return $merged; | |
| } | |
| my_parse_str($query, $array); | |
| ?> | 
@infrat I think there might be 2 slight problems.
- 
dynamic keys in encoded query strings are not properly detected. In parseUrlthe dynamic key check should be changed to:$dynamicKey = (false !== strpos($pair, '[]=')) || (false !== strpos($pair, '%5B%5D=')); 
- 
in arrayMergeRecursiveDistinctandelseclause is missing, causing values to be mistakenly overwritten. Should be changed to:if ($dynamicKey) { $merged[] = $value; } else { $merged[$key] = $value; } 
Thanks a lot guys for sharing this.
I had some issues with the functions when using dynamic keys, and after a few hours of head banging, here is the final version that seems to be working for me:
// https://gist.github.com/rubo77/6821632
/**
* @param $string
* @return array|bool
*/
function parseUrl($string) {
  if($string==='') {
    return false;
  }
  
  $result = array();
  // find the pairs "name=value"
  $pairs = explode('&', $string);
  foreach ($pairs as $pair) {
    $dynamicKey = (false !== strpos($pair, '[]=')) || (false !== strpos($pair, '%5B%5D='));
    // use the original parse_str() on each element
    parse_str($pair, $params);
    $k = key($params);
    if (!isset($result[$k])) {
      $result += $params;
    } else {
      $result[$k] = arrayMergeRecursiveDistinct($result[$k], $params[$k], $dynamicKey);
    }
  }
  return $result;
}
/**
* @param array $array1
* @param array $array2
* @param $dynamicKey
* @return array
*/
function arrayMergeRecursiveDistinct(array &$array1, array &$array2, $dynamicKey) {
  $merged = $array1;
  foreach ($array2 as $key => &$value) {
    if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
      $merged[$key] = arrayMergeRecursiveDistinct($merged[$key], $value, $dynamicKey);
    } else {
      if ($dynamicKey) {
        
        if ( ! isset( $merged[$key] ) ) {
          
          $merged[$key] = $value;
          
        } else {
          
          if ( is_array( $merged[$key] ) ) {
            
            $merged[$key] = array_merge_recursive( $merged[$key], $value );
            
          } else {
            
            $merged[] = $value;
            
          }
          
        }
        
      } else {
        
        $merged[$key] = $value;
        
      }
    }
  }
  return $merged;
}
This last function still has inconsistent behaviour with parse_str:
$string = "key[][index]=1&key[][index]=2&key[][index]=3&var2[][]=1&var2[][]=2";
$parsed = my_parse_str($string);
print_r($parsed);
parse_str($string, $parsedOrig);
print_r($parsedOrig);
The goal, as I understood it, was to mirror the functionality of parse_str without the limitation of the max_input_vars limit.
OK, the following seems to mirror parse_str perfectly, including dynamic keys which are not last. Specifically, the my_parse_str function becomes:
function my_parse_str($string)
{
    if ($string === '') {
        return [];
    }
    $vars = explode ('&', $string);
    $result = [];
    $count = [];
    foreach ($vars as $var) {
        $dkIndex = strpos($var, '[]');
        if (false === $dkIndex) {
             $dkIndex = strpos ($var, '%5B%5D');
        }
        if (false !== $dkIndex) {
            $varPrefix = substr($var, 0, $dkIndex);
            if (!isset ($count [$varPrefix])) {
                $count [$varPrefix] = 0;
            }
            $var = str_replace(['[]', '%5B%5D'], "[" . $count [$varPrefix]++ . "]", $var);
        }
        // use the original parse_str() on each element
        $params = null;
        parse_str ($var, $params);
        $k = key ($params);
        if (!isset($result[$k])) {
            $result += $params;
        }
        else {
            $result[$k] = array_merge_recursive_distinct ($result[$k], $params[$k]);
        }
    }
    return $result;
}
This works with the following test case:
$string = "key[][index]=1&key[][index]=2&key[][index]=3&var2[][]=1&var2[][]=2&key[1][index]=hi";
$parsed = my_parse_str($string);
print_r ($parsed);
parse_str ($string, $results);
print_r ($results);
Note carefully the overwritten second key[][index]=2 which is consistent with parse_str's behaviour.
And again, as @marek-saji noticed, there's still some problems when dynamic-keys notation such as:
"key[]=1&key[]=2&key[]=3"
I'd resolved it with passing $dynamicKey flag to merging function: