-
-
Save rubo77/6821632 to your computer and use it in GitHub Desktop.
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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); | |
?> |
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.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@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:in
arrayMergeRecursiveDistinct
andelse
clause is missing, causing values to be mistakenly overwritten. Should be changed to: