Посмотрев на решение Рока, я нашел версию, которая учитывает ограничения в моем ответе ниже, crb выше и решение Рока, а также. Смотрите мою улучшенную версию .
@ ответ CRB выше - хорошее начало, но есть пара проблем.
- Перерабатывает все, что является излишним; только те поля, которые имеют "." в названии должны быть переработаны.
- Он не может обрабатывать массивы так же, как это делает нативная обработка PHP, например, для клавиш типа "foo.bar []".
Решение, приведенное ниже, теперь решает обе эти проблемы (обратите внимание, что оно было обновлено с момента первоначальной публикации). Это примерно на 50% быстрее, чем мой ответ выше в моем тестировании, но не будет обрабатывать ситуации, когда данные имеют одинаковый ключ (или ключ, который извлекается одинаково, например, foo.bar и foo_bar оба извлекаются как foo_bar).
<?php
public function fix2(&$target, $source, $keep = false) {
if (!$source) {
return;
}
preg_match_all(
'/
# Match at start of string or &
(?:^|(?<=&))
# Exclude cases where the period is in brackets, e.g. foo[bar.blarg]
[^=&\[]*
# Affected cases: periods and spaces
(?:\.|%20)
# Keep matching until assignment, next variable, end of string or
# start of an array
[^=&\[]*
/x',
$source,
$matches
);
foreach (current($matches) as $key) {
$key = urldecode($key);
$badKey = preg_replace('/(\.| )/', '_', $key);
if (isset($target[$badKey])) {
// Duplicate values may have already unset this
$target[$key] = $target[$badKey];
if (!$keep) {
unset($target[$badKey]);
}
}
}
}