Отримайте 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.