Декодирование строк запроса в PHP

Итак, я написал реализацию REST API, используя mod_rewrite и PHP. Я принимаю строку запроса через тело запросов HTTP DELETE (... коллективный стон?). Аргументы о мудрости обоих предыдущих утверждений в стороне, я обнаружил, что PHP не анализирует тело запроса DELETE автоматически (т. е. $_POST пуст, несмотря на то, что строка запроса, закодированная в форме, появляется в теле запроса). Меня это особо не удивило. Что меня удивило, так это то, что я не смог найти встроенную функцию PHP для разбора строки запроса?? Я просто что-то упустил из виду? Я могу сделать что-то вроде:

public function parseQS($queryString, &$postArray){
  $queryArray = explode('&', $queryString);
  for($i = 0; $i < count($queryArray); $i++) {
    $thisElement = split('=', $queryArray[$i]);
    $postArray[$thisElement[0]] = htmlspecialchars(urldecode($thisElement[1]));
  }
}

... просто кажется странным, что для этого не было бы встроенного PHP. Кроме того, я подозреваю, что мне не следует использовать htmlspecialcharacters и urldecode для очистки значений, закодированных в форме... это другой вид кодирования, но у меня также возникают проблемы с определением, какую функцию PHP я должен использовать для декодирования данных, закодированных в форме. .

Любые предложения будут оценены.


person codemonkey    schedule 16.07.2009    source источник


Ответы (7)


Там есть parse_str. Плохое имя, но делает то, что вы хотите. И обратите внимание, что он ничего не возвращает, второй аргумент передается по ссылке.

person Ionuț G. Stan    schedule 16.07.2009
comment
parse_str не обрабатывает синтаксический анализ $_GET точно так же, как это делает PHP (не знаю, почему). Смотрите мой ответ для моего решения. - person Kendall Hopkins; 22.06.2012

Для этого есть функция http://php.net/parse_str. Поскольку PHP должен делать это сам, нет никаких причин не открывать его для использования в API.

Разбирает строку на переменные void parse_str (string $str [, array &$arr])

Разбирает str, как если бы это была строка запроса, переданная через URL-адрес, и устанавливает переменные в текущей области.

<?php
$str = "first=value&arr[]=foo+bar&arr[]=baz";

parse_str($str, $output);
echo $output['first'];  // value
echo $output['arr'][0]; // foo bar
echo $output['arr'][1]; // baz
person Alister Bulman    schedule 16.07.2009

parse_str подходит для простых вещей, но это не то же самое, что встроенный в PHP способ создания магической переменной $_GET. Почему?!? Понятия не имею. Я разработал свою собственную версию, которая, по моему мнению, точно соответствует синтаксическому анализу PHP (дайте мне знать, если вы найдете какие-либо примеры, демонстрирующие обратное).

function betterParseStr( $string )
{
    return array_reduce( explode( "&", $string ), function( $array, $string_piece ) {
        if( $string_piece === "" ) return $array;
        $equal_offset = strpos( $string_piece, "=" );
        if( $equal_offset === FALSE ) {
            $key = urldecode( $string_piece );
            $value = "";
        } else {
            $key = urldecode( substr( $string_piece, 0, $equal_offset ) );
            $value = urldecode( substr( $string_piece, $equal_offset + 1 ) );
        }
        if( preg_match( "/^([^\[]*)\[([^\]]*)](.*)$/", $key, $matches ) ) {
            $key_path = array( $matches[1], $matches[2] );
            $rest = $matches[3];
            while( preg_match( "/^\[([^\]]*)](.*)$/", $rest, $matches ) ) {
                $key_path[] = $matches[1];
                $rest = $matches[2];
            }
        } else {
            //replace first [ for _
            //why?!? idk ask PHP it does
            //Example: ?key[[=value -> array( "key_[" => "value" )
            $key_path = array( preg_replace('/\[/', '_', $key, 1 ) );
        }
        if( strlen( $key_path[0] ) > 0 && substr( $key_path[0], 0, 1 ) !== "[" ) {
            $current_node = &$array;
            $last_key = array_pop( $key_path );
            $resolve_key = function( $key, array $array ) {
                if( $key === "" || $key === " " ) {
                    $int_array = array_filter( array_keys( $array ), function( $key ) { return is_int( $key ); } );
                    $key = $int_array ? max( $int_array ) + 1 : 0;
                }
                return $key;
            };
            foreach( $key_path as $key_path_piece ) {
                $key_path_piece = $resolve_key( $key_path_piece, $current_node );
                if( ! array_key_exists( $key_path_piece, $current_node ) || ! is_array( $current_node[$key_path_piece] ) ) {
                    $current_node[$key_path_piece] = array();
                }
                $current_node = &$current_node[$key_path_piece];
            }
            $current_node[$resolve_key( $last_key, $current_node )] = $value;
        }
        return $array;
    }, array() );
}
person Kendall Hopkins    schedule 14.06.2012

Вы можете использовать функцию parse_str:

parse_str($queryString, $args);
person Gumbo    schedule 16.07.2009

http://us2.php.net/manual/en/function.parse-url.php

parse_url поможет вам получить часть DOCUMENT_URI, содержащую фактический запрос.

Затем вы можете передать этот раздел в parse_str для извлечения отдельных элементов из запроса.

http://us2.php.net/manual/en/function.parse-str.php

person Nolte    schedule 16.07.2009
comment
интересно... Интересно, есть ли преимущество в использовании этого вместо @file_get_contents('php://input')... что я и использую сейчас. - person codemonkey; 16.07.2009

Я создал простую библиотеку для анализа строки запроса для фильтрации, сортировки и выбора полей для моего API для отдыха. наивная версия odata . строка запроса преобразуется в объект и/или массивы объектов. например:

фильтры:

www.example.com/resource?@filters=filedName operator 'the value'

доступные операторы eq ,ne, gt, lt, like ,ilike , le, ge

$filtersResult = $parser->filters();

$filtersResult[0]->field // name
$filtersResult[0]->operator // eq
$filtersResult[0]->getOperator() // "="
$filtersResult[0]->value // 'what ever'

Сортировать :

//name is asc , surname desc
@orderby=name,-surname
$sorts = $parser->orderBy() // you can set defaults if u want
$sorts[0]->filed //name 
$sorts[0]->direction //asc

$sorts[1]->filed //surname 
$sorts[1]->direction //desc

для встраивания:

@embed=resourceOne(@fields=name,code)(@filters=nameembed eq 'what ever'),mobiles(@orderby=sortFieldOne)

$embedResult = $parser->embed(); //return array of embed each              
//object contains filters , sort , fields | empty array 

$embedResult[0]->resource // resourceOne
$embedResult[0]->fields // array of fields  [name,code]
$embedResult[0]->filters // array of filters or empty array 

$embedResult[1]->resource // mobiles
$embedResult[1]->orderBy // array of order by objects

простой парсер

person Yehia    schedule 19.09.2016

person    schedule
comment
кто-то проголосовал за это? он явно шутил ... на самом деле не предлагая мне обернуть встроенное, используя мою функцию. - person codemonkey; 16.07.2009