Instantly share code, notes, and snippets.

Embed
What would you like to do?
This is a replacement for the original idea how to cirumvent the max_input_vars limitation, that uses the original parse_str() on each element of the query to parse
<?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);
?>
@rubo77

This comment has been minimized.

Owner

rubo77 commented Oct 4, 2013

used for my script to circumvent the max_input_vars limitation in PHP https://gist.github.com/rubo77/6815945

@marek-saji

This comment has been minimized.

marek-saji commented Dec 10, 2013

This does not work, when elements with empty keys appear in query string (like a[]=1&a[]=2). Using array_merge in line 23 fixes that.

@sebastianwebb

This comment has been minimized.

sebastianwebb commented Nov 3, 2014

Unfortunately this function isn't fully working for my multidimensional array of 6/7 levels deep. I feel there is probably a need for a recursive function somewhere. Or the array_merge technique marek-saji flagged. I'm just having some issues getting my head around it. I'll post an answer here if I manage to crack it.

@sebastianwebb

This comment has been minimized.

sebastianwebb commented Nov 3, 2014

OK so I managed to sort this in the end. I adjusted the function by removing the urldecode() function (which was causing probs if any values had a "&" - and it's redundant because pasre_str calls urldecode).

Critically though, I replaced line 23 with a recursive array merge function, which is a slight adaptation of the native array_merge_recursive function. The native one was creating unwanted additional keys.

~ added in Revision 7 ~

@rubo77

This comment has been minimized.

Owner

rubo77 commented Apr 21, 2016

@sebastianwebb: Thanks, I added your version

@infrat

This comment has been minimized.

infrat commented May 25, 2016

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:

/**
 * @param $string
 * @return array|bool
 */
private 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,'[]=');
        // use the original parse_str() on each element
        parse_str($pair, $params);
        $k = key($params);
        if (!isset($result[$k])) {
            $result += $params;
        } else {
            $result[$k] = $this->arrayMergeRecursiveDistinct($result[$k], $params[$k], $dynamicKey);
        }
    }
    return $result;
}

/**
 * @param array $array1
 * @param array $array2
 * @param $dynamicKey
 * @return array
 */
private 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] = self::arrayMergeRecursiveDistinct($merged[$key], $value, $dynamicKey);
        } else {
            if ($dynamicKey) {
                $merged[] = $value;
            }
            $merged[$key] = $value;
        }
    }
    return $merged;
}
@kgilden

This comment has been minimized.

kgilden commented Oct 21, 2016

@infrat I think there might be 2 slight problems.

  • dynamic keys in encoded query strings are not properly detected. In parseUrl the dynamic key check should be changed to:

    $dynamicKey = (false !== strpos($pair, '[]=')) || (false !== strpos($pair, '%5B%5D='));
  • in arrayMergeRecursiveDistinct and else clause is missing, causing values to be mistakenly overwritten. Should be changed to:

    if ($dynamicKey) {
        $merged[] = $value;
    } else {
        $merged[$key] = $value;
    }
@OriginalEXE

This comment has been minimized.

OriginalEXE commented Feb 1, 2017

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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment