Отримайте PHP, щоб припинити заміну '.' символів у масивах $ _GET або $ _POST?


76

Якщо я передаю змінні PHP з .їхніми іменами через $ _GET, PHP автоматично замінює їх _символами. Наприклад:

<?php
echo "url is ".$_SERVER['REQUEST_URI']."<p>";
echo "x.y is ".$_GET['x.y'].".<p>";
echo "x_y is ".$_GET['x_y'].".<p>";

... виводить наступне:

url is /SpShipTool/php/testGetUrl.php?x.y=a.b
x.y is .
x_y is a.b.

... моє питання полягає в наступному: чи існує якийсь - небудь спосіб , яким я можу отримати це зупинити? Не можу за все життя зрозуміти, що я зробив, щоб цього заслужити

Версія PHP, з якою я працюю, - це 5.2.4-2ubuntu5.3.


.. Чому б вам просто не перетворити всі крапки на якийсь маркер, як, наприклад, у (~ # ~), а потім опублікувати його? Отримуючи вари, ви можете потім перетворити їх назад .. Це тому, що іноді НАМ ПОТРІБНО розміщувати підкреслення .. і ми втрачаємо їх, якщо перетворюємо всі "_" на "." ...
— Фернандо

З самого запиту на отримання ви можете вказати ім'я користувача на зразок "concat (ім'я, '_', прізвище) як ім'я користувача.
— Каспар Мері

@Kaspar Mary ... база даних налаштована на те, щоб мати стовпці ім'я користувача та статус, а імена користувачів зберігаються як firstname.lastname, тому я не можу використовувати будь-який concat у sql, оскільки вони вже з'єднані з a.
— Роб

@Crisp Дякую за коментар! (at)
— Гра

Чому немає коментаря щодо видалення? :)
— Кріс Принс

Відповіді:


66

Ось пояснення PHP.net, чому це робиться:

Крапки у вхідних іменах змінних

Як правило, PHP не змінює імена змінних, коли вони передаються в сценарій. Однак слід зазначити, що крапка (крапка, крапка) не є допустимим символом у назві змінної PHP. З причини, подивіться на це:

<?php
$varname.ext;  /* invalid variable name */
?>

Тепер парсер бачить змінну з ім'ям $ varname, за якою слідує оператор конкатенації рядків, за яким слідує оголення (тобто рядок без котирувань, який не відповідає жодному відомому ключу чи зарезервованим словам) 'ext'. Очевидно, це не має запланованого результату.

З цієї причини важливо відзначити, що PHP автоматично замінить будь-які крапки у вхідних іменах змінних на підкреслення.

Це з http://ca.php.net/variables.external .

Крім того, згідно з цим коментарем ці інші символи перетворюються на підкреслення:

Повний список символів імен полів, які PHP перетворює на _ (підкреслення), є таким (не лише крапкою):

  • chr (32) () (пробіл)
  • chr (46) (.) (крапка)
  • chr (91) ([) (відкрита квадратна дужка)
  • chr (128) - chr (159) (різні)

Отже, схоже, ви застрягли в цьому, тому вам доведеться перетворити підкреслення назад у крапки у вашому сценарії, використовуючи пропозицію dawnerd (я б просто використав str_replace .)


20
Це чудове пояснення чому , але не дає відповіді на вихідне запитання "чи є спосіб зупинити його"; інші відповіді нижче дають відповідь на вихідне запитання.
— El Yobo

1
@ElYobo, @JeremyRuten; гарне пояснення чому? Я використовую PHP 5.4, і PHP все ще робить це. Я також хотів би знати, чому це ще не застаріло. Я бачу лише дві причини його збереження; register_globals (застаріло з 5.3), а також для зручності ~ робити те, що робить глобальний регістр, робить це вручну (у такому випадку тягар повинен лежати на людині, яка робить це, щоб зіставити імена var, як вони вважають за потрібне IMO).
— напівзахищений

1
Я вважаю зворотну сумісність? Хороший момент, якщо глобальні регістри реєструються на шляху додо, ця дивна "функціональність" може піти так само.
— El Yobo

За допомогою php7 зареєструвати глобальні глобальні системи вже зійшли на захід, але проблема все ще присутня.
— magallanes

59

Давно відповіли на запитання, але насправді є краща відповідь (або обхід). PHP дозволяє переглядати необроблений вхідний потік , тож ви можете зробити щось подібне:

$query_string = file_get_contents('php://input');

що дасть вам масив $ _POST у форматі рядка запиту, періоди, як вони повинні бути.

Потім ви можете проаналізувати його, якщо вам потрібно (відповідно до коментаря POSTer )

<?php
// Function to fix up PHP's messing up input containing dots, etc.
// `$source` can be either 'POST' or 'GET'
function getRealInput($source) {
    $pairs = explode("&", $source == 'POST' ? file_get_contents("php://input") : $_SERVER['QUERY_STRING']);
    $vars = array();
    foreach ($pairs as $pair) {
        $nv = explode("=", $pair);
        $name = urldecode($nv[0]);
        $value = urldecode($nv[1]);
        $vars[$name] = $value;
    }
    return $vars;
}

// Wrapper functions specifically for GET and POST:
function getRealGET() { return getRealInput('GET'); }
function getRealPOST() { return getRealInput('POST'); }
?>

Надзвичайно корисний для параметрів OpenID, які містять обидва символи '.' та "_", кожен із певним значенням!


5
Щоб зробити цю роботу з параметрами GET замінити file_get_contents("php://input")на $_SERVER['QUERY_STRING'].
— Сарел Бота

І ви можете зробити те саме для печива, використовуючи$_SERVER['COOKIES']
— Marcin

4
Це хороший початок, але з цим є кілька проблем. Він не обробляє значення масиву (наприклад, foo.bar [] = blarg не закінчиться як масив, він опиниться як скалярна змінна, що називається foo.bar []). У нього також є багато накладних витрат, оскільки він обробляє всі значення, незалежно від того, є в них період чи ні.
— El Yobo

Дивіться моє рішення нижче , яке виправляє проблеми з реалізацією Рока.
— El Yobo

З якоїсь причини $ query_string = file_get_contents ('php: // input'); повертає для мене порожній рядок.
— Chris Prince

27

Висвітлюючи фактичну відповідь Йохана у коментарі вище - я просто обгорнув всю свою публікацію масивом верхнього рівня, який повністю обходить проблему, не вимагаючи важкої обробки.

У тій формі, яку ви робите

<input name="data[database.username]">  
<input name="data[database.password]">  
<input name="data[something.else.really.deep]">  

замість

<input name="database.username"> 
<input name="database.password"> 
<input name="something.else.really.deep">  

а в обробнику постів просто розгорніть його:

$posdata = $_POST['data'];

Для мене це була зміна у два рядки, оскільки мої погляди були повністю шаблонні.

FYI. Я використовую крапки в іменах полів для редагування дерев згрупованих даних.


4
Насправді дуже елегантне і практичне рішення, з побічною перевагою збереження даних форми з гарним простором імен.
— Робінмітра

1
Це повністю вирішує проблему, і вона повинна була бути прийнятою відповіддю.
— Брайан Клуг,

20

Робота цієї функції - це чудова ідея, яку я придумав під час літніх канікул 2013 року.

Наприклад, він відповідає стандартам і має підтримку глибоких масивів a.a[x][b.a]=10. Він використовує parse_str()за кадром певну цільову попередню обробку.

function fix($source) {
    $source = preg_replace_callback(
        '/(^|(?<=&))[^=[&]+/',
        function($key) { return bin2hex(urldecode($key[0])); },
        $source
    );

    parse_str($source, $post);

    $result = array();
    foreach ($post as $key => $val) {
        $result[hex2bin($key)] = $val;
    }
    return $result;
}

І тоді ви можете застосувати це так, залежно від джерела:

$_POST   = fix(file_get_contents('php://input'));
$_GET    = fix($_SERVER['QUERY_STRING']);
$_COOKIE = fix($_SERVER['HTTP_COOKIE']);

Для PHP нижче 5.4: використовуйте base64_encodeзамість bin2hexта base64_decodeзамість hex2bin.


Дякую за це. Будь ласка, також оновіть його для глибоких масивів a [2] [5], якщо у вас є час.
— Йохан

@ Джохан, глибокі масиви працюють. a[2][5]=10виробляє array(1) { ["a"]=> array(1) { [2]=> array(1) { [5]=> string(2) "10" } } }.
— Рок Краль

1
О, я зрозумів, це справді так, просто перевірив. Php не перетворює крапки тощо в індекси масивів, непокоїть лише верхній рівень імені масиву: php_touches_this [nochangeshere] [nochangeshere]. Чудово. Дякую.
— Йохан

Я хотів би бачити ваші орієнтири, оскільки це суперечить тестуванню, яке я провів кілька місяців тому. Крім того, я щойно стикався з ситуацією, коли мені потрібно обробляти періоди в розміщених полях файлів, на які ще немає відповідей; будь-які ідеї?
— El Yobo

Ви побачите їх досить скоро, наразі не маєте часу, але можете представити своє. * Для завантаження файлів потрібен тип даних, що складається з декількох частин / форми, який не передається на вхід php: //. Тому це все ще дуже хакерсько робити. Див .: stackoverflow.com/questions/1361673/get-raw-post-data
— Рок Краль

7

Це відбувається тому, що крапка є неприпустимим символом в назві змінної, причина якої криється дуже глибоко у реалізації PHP, тому простих виправлень (поки) немає.

Тим часом ви можете вирішити цю проблему, виконавши:

  1. Доступ до необроблених даних запитів через php://inputдані POST або $_SERVER['QUERY_STRING']GET
  2. Використання функції перетворення.

Наведена нижче функція перетворення (PHP> = 5.4) кодує імена кожної пари ключ-значення в шістнадцяткове представлення, а потім виконує регулярне parse_str(); Після цього він повертає шістнадцяткові імена назад у початкову форму:

function parse_qs($data)
{
    $data = preg_replace_callback('/(?:^|(?<=&))[^=[]+/', function($match) {
        return bin2hex(urldecode($match[0]));
    }, $data);

    parse_str($data, $values);

    return array_combine(array_map('hex2bin', array_keys($values)), $values);
}

// work with the raw query string
$data = parse_qs($_SERVER['QUERY_STRING']);

Або:

// handle posted data (this only works with application/x-www-form-urlencoded)
$data = parse_qs(file_get_contents('php://input'));

що мало б статися, якби це потрібно було використати для чогось іншого, що було надіслано, і мені насправді потрібна _ у змінній?
— Роб

@Rob Я додав результат на основі вашого запитання; це працює, як очікувалося, тому що я не чіпаю підкреслення.
— Jack

Примітка: Це відредаговане рішення, яке згодом скопіювало мій код та мою ідею (див. Журнал змін). Його повинні видалити модератори.
— Rok Kralj

Мабуть, вам було досить добре взяти bin2hex()ідею у мене, тож чи можемо ми просто відмовитись від цієї безглуздої ворожнечі?
— Ja͢ck

Ну, я просто поміняв його місцями замість кодування base64. Вигода? Нічого, крім невеликого прискорення. Навіщо редагувати абсолютно прекрасне рішення для копіювання чужого?
— Rok Kralj,

5

Цей підхід є зміненою версією Рока Краля, але з деякими налаштуваннями для роботи, щоб підвищити ефективність (уникає зайвих зворотних викликів, кодування та декодування на незадіяних клавішах) та правильної обробки ключів масиву.

Перелік тестів доступний, і будь-які відгуки чи пропозиції вітаються тут чи там.

public function fix(&$target, $source, $keep = false) {                        
    if (!$source) {                                                            
        return;                                                                
    }                                                                          
    $keys = array();                                                           

    $source = preg_replace_callback(                                           
        '/                                                                     
        # 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',                                                                   
        function ($key) use (&$keys) {                                         
            $keys[] = $key = base64_encode(urldecode($key[0]));                
            return urlencode($key);                                            
        },                                                                     
    $source                                                                    
    );                                                                         

    if (!$keep) {                                                              
        $target = array();                                                     
    }                                                                          

    parse_str($source, $data);                                                 
    foreach ($data as $key => $val) {                                          
        // Only unprocess encoded keys                                      
        if (!in_array($key, $keys)) {                                          
            $target[$key] = $val;                                              
            continue;                                                          
        }                                                                      

        $key = base64_decode($key);                                            
        $target[$key] = $val;                                                  

        if ($keep) {                                                           
            // Keep a copy in the underscore key version                       
            $key = preg_replace('/(\.| )/', '_', $key);                        
            $target[$key] = $val;                                              
        }                                                                      
    }                                                                          
}                                                                              

Бум, це у мене спрацювало ідеально, спасибі El Yobo / Rok. Використання його в проекті CodeIgniter 2.1.3.
— xref

Я б зауважив, що якщо входять значення, у яких уже немає% 20 сутностей, наприклад, "Деякий ключ = Якесь значення", тоді результат цієї функції - "Деякий_Ключ = Якесь значення", можливо, регулярний вираз можна змінити?
— xref

Регулярний вираз можна налаштувати, щоб зафіксувати простір, закодований не за URL-адресою ... але якщо ваше джерело ще не закодовано за допомогою URL-адреси, то, ймовірно, будуть інші проблеми, оскільки обробка завжди декодує та кодує рядки, тоді parse_strвиклик знову буде urldecode. Що ви намагаєтеся розібрати, що ще не закодовано?
— Ель Йобо

Дякуємо за атрибуцію. Хоча, я можу попередити, що ваш код може працювати гірше, оскільки POST зазвичай складають лише кілька сотень байт. Тут я віддаю перевагу простоті.
— Рок Краль

1
Ви десь оцінювали ці показники? Мені цікаво побачити, в яких сценаріях це повільніше, оскільки все, що я тестував, коливалося від тієї ж швидкості, що і ваша, і вдвічі швидше. Я підозрюю, що різниця полягає у типі речей, на яких вона була протестована :) Ви можете легко додати деякі перевірки синхронізації в мою суть, щоб побачити, як це відбувається, чому б не порівняти ваші з однаковими введеними та опублікованими результатами та часом?
— El Yobo

4

Причиною цього є стара функціональність PHP register_globals. . Символ не є дійсним символом в назві змінної, тому PHP покриває його підкресленням, щоб переконатись у сумісності.

Коротше кажучи, не найкраща практика робити періоди у змінних URL.


1
Також не є гарною ідеєю включати register_globals. Насправді його слід відключити прямо зараз, якщо це можливо.
— dawnerd

1
register_globals фактично вимкнено, як і за замовчуванням у PHP5. > The. Символ не є допустимим символом в назві змінної На жаль, я не хочу використовувати це як ім'я змінної (я зберігаю його як ключ у словнику $ _GET), тому ця "продуманість" у PHP не додає значення :-( Ну добре ...

Неважливо, ввімкнено чи вимкнено register_globals. PHP все ще виконує заміну.
— Джеремі Приветт,

3

Якщо ви шукаєте будь-який спосіб буквально змусити PHP припинити заміну '.' символів у масивах $ _GET або $ _POST, тоді одним із таких способів є модифікація джерела PHP (і в цьому випадку це відносно просто).

ПОПЕРЕДЖЕННЯ: Зміна джерела PHP C - це вдосконалений варіант!

Також перегляньте це звіт про помилки PHP, який пропонує таку ж модифікацію.

Для дослідження вам потрібно:

  • завантажити вихідний код на PHP
  • відключити . перевірку заміни
  • ./configure , make та розгорнути вашу власну збірку PHP

Сама зміна джерела є тривіальною і передбачає оновлення лише половини одного рядка в main/php_variables.c:

Примітка: порівняно з оригіналом || *p == '.' було залишено коментарі


Приклад результату:

задано QUERY_STRING a.a[]=bb&a.a[]=BB&c%20c=dd, працює<?php print_r($_GET); зараз видає:

Масив
(
    [aa] => Масив
        (
            [0] => bb
            [1] => BB
        )

    [c_c] => dd
)

Примітки:

  • цей патч стосується лише вихідного питання (зупиняє заміну крапок, а не пробілів).
  • запуск на цьому патчі буде швидшим, ніж рішення на рівні сценарію, але ці чисто-.php-відповіді все-таки переважніше (оскільки вони уникають зміни самого PHP).
  • теоретично тут можливий підхід із поліфілом, який міг би поєднувати підходи - перевірити зміну рівня С, використовуючи parse_str()та (якщо недоступний) повернення до більш повільних методів.

1
Ви не повинні робити це так ніколи, однак, +1 за зусилля.
— Rok Kralj

2

Моє рішення цієї проблеми було швидким і брудним, але мені все одно подобається. Я просто хотів опублікувати список імен файлів, які були перевірені у формі. Раніше я base64_encodeкодував імена файлів у розмітці, а потім просто декодував їх base64_decodeдо їх використання.


2

Подивившись на рішення Рока, я придумав версію, яка стосується обмежень у моїй відповіді нижче, 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]);                                       
            }                                                                  
        }                                                                      
    }                                                                          
}                                                                              

-1. Чому? 1. Космос %20- це також спеціальний персонаж, який перетворюється на підкреслення. 2. Ваш код попередньо обробляє всі дані, оскільки preg_match_allповинен просканувати все, навіть якщо ви скажете, що ні. 3. Ваш код не в таких прикладів: a.b[10]=11.
— Рок Краль,

Ви маєте рацію щодо простору, дякую. Моє пояснення вже вказує на те, що мій підхід не обробляє масиви, тому я не зовсім впевнений, чому ви на це вказуєте. preg_match_allповинен "обробити" один рядок, а не витягувати та обробляти всі незмінені ключі та значення, тож ви там теж трохи відстали. Тим не менш, ваш підхід з parse_stringвиглядає як цікавий підхід, який, трохи поправляючи, може бути кращим :)
— El Yobo

Ви говорите, що ви витягуєте лише зачеплені ключі, але з точки зору складності обчислень - ні. Ви говорите, як у вас був якийсь довільний доступ, щоб отримати лише пошкоджені ключі, але навіть якщо відсутні присутні ключі, вам потрібно отримати доступ до всієї пам'яті. Якщо у вас є пост з 100 мегабайт даних, це не має значення , що ви витягаєте, обидва підходи є лінійними O(n). Насправді ви погіршуєте складність, використовуючи in_array()функцію, як зазначено вище.
— Rok Kralj

Я переглядаю 100 мегів один раз, не розділяючи їх (що негайно подвоює пам’ять), потім знову розділяючи (знову подвоюючи), як у методі crb, я теж це порівнював. Позначення Big O взагалі не враховує використання пам'яті, і ця реалізація все одно не використовує in_array. Крім того, якщо ви хочете провести деякі тести, ви помітите, що вищезазначене все одно значно швидше; не O (n) проти O (n ^ 2), але один лінійний підхід все одно може бути швидшим за інший ... а цей -;)
— El Yobo

Інша основна перевага, яку має такий підхід, полягає в тому, що перевага у швидкості є найбільшою, коли взагалі немає роботи, тобто коли жодна клавіша не має крапок чи пробілів; це означає, що у нього мінімальні накладні витрати, якщо ви залишите його на обробку всіх запитів, оскільки він майже не виконує жодної роботи (один регулярний вираз), проти вилучення та кодування всіх ключів кілька разів.
— El Yobo

0

Ну, функція, яку я включаю нижче, "getRealPostArray ()", не є гарним рішенням, але вона обробляє масиви і підтримує обидва імена: "alpha_beta" і "alpha.beta":

  <input type='text' value='First-.' name='alpha.beta[a.b][]' /><br>
  <input type='text' value='Second-.' name='alpha.beta[a.b][]' /><br>
  <input type='text' value='First-_' name='alpha_beta[a.b][]' /><br>
  <input type='text' value='Second-_' name='alpha_beta[a.b][]' /><br>

тоді як var_dump ($ _ POST) видає:

  'alpha_beta' => 
    array (size=1)
      'a.b' => 
        array (size=4)
          0 => string 'First-.' (length=7)
          1 => string 'Second-.' (length=8)
          2 => string 'First-_' (length=7)
          3 => string 'Second-_' (length=8)

var_dump (getRealPostArray ()) видає:

  'alpha.beta' => 
    array (size=1)
      'a.b' => 
        array (size=2)
          0 => string 'First-.' (length=7)
          1 => string 'Second-.' (length=8)
  'alpha_beta' => 
    array (size=1)
      'a.b' => 
        array (size=2)
          0 => string 'First-_' (length=7)
          1 => string 'Second-_' (length=8)

Функція, для чого вона варта:

function getRealPostArray() {
  if ($_SERVER['REQUEST_METHOD'] !== 'POST') {#Nothing to do
      return null;
  }
  $neverANamePart = '~#~'; #Any arbitrary string never expected in a 'name'
  $postdata = file_get_contents("php://input");
  $post = [];
  $rebuiltpairs = [];
  $postraws = explode('&', $postdata);
  foreach ($postraws as $postraw) { #Each is a string like: 'xxxx=yyyy'
    $keyvalpair = explode('=',$postraw);
    if (empty($keyvalpair[1])) {
      $keyvalpair[1] = '';
    }
    $pos = strpos($keyvalpair[0],'%5B');
    if ($pos !== false) {
      $str1 = substr($keyvalpair[0], 0, $pos);
      $str2 = substr($keyvalpair[0], $pos);
      $str1 = str_replace('.',$neverANamePart,$str1);
      $keyvalpair[0] = $str1.$str2;
    } else {
      $keyvalpair[0] = str_replace('.',$neverANamePart,$keyvalpair[0]);
    }
    $rebuiltpair = implode('=',$keyvalpair);
    $rebuiltpairs[]=$rebuiltpair;
  }
  $rebuiltpostdata = implode('&',$rebuiltpairs);
  parse_str($rebuiltpostdata, $post);
  $fixedpost = [];
  foreach ($post as $key => $val) {
    $fixedpost[str_replace($neverANamePart,'.',$key)] = $val;
  }
  return $fixedpost;
}

0

Використовуючи crb, я хотів відтворити $_POSTмасив в цілому, хоча майте на увазі, вам все одно доведеться переконатися, що ви правильно кодуєте та декодуєте як на клієнті, так і на сервері. Важливо розуміти, коли персонаж справді недійсний, а він справді дійсний . Крім того, люди повинні все одно і завжди уникати даних клієнта, перш ніж використовувати їх із будь-якою командою бази даних без винятку .

<?php
unset($_POST);
$_POST = array();
$p0 = explode('&',file_get_contents('php://input'));
foreach ($p0 as $key => $value)
{
 $p1 = explode('=',$value);
 $_POST[$p1[0]] = $p1[1];
 //OR...
 //$_POST[urldecode($p1[0])] = urldecode($p1[1]);
}
print_r($_POST);
?>

Я рекомендую використовувати це лише для окремих випадків, за винятком я не впевнений у негативних моментах розміщення цього у верхній частині вашого основного файлу заголовка.


0

Моє поточне рішення (на основі попередніх відповідей теми):

function parseQueryString($data)
{
    $data = rawurldecode($data);   
    $pattern = '/(?:^|(?<=&))[^=&\[]*[^=&\[]*/';       
    $data = preg_replace_callback($pattern, function ($match){
        return bin2hex(urldecode($match[0]));
    }, $data);
    parse_str($data, $values);

    return array_combine(array_map('hex2bin', array_keys($values)), $values);
}

$_GET = parseQueryString($_SERVER['QUERY_STRING']);

будь-ласка, додайте пояснення, яке буде корисним кожному, хто прочитає вашу відповідь.
— Прафулла Кумар Саху
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.