Question

Okay, so I've written a REST API implementation using mod_rewrite and PHP. I'm accepting a query string via the body of HTTP DELETE requests (... collective groan?). Arguments about the wisdom of both previous statements aside, what I've found is that PHP doesn't automatically parse the request body of DELETE requests (i.e. $_POST is empty despite form-encoded query string appearing in body of request). This didn't particularly surprise me. What I did find surprising was that I've been unable to find a built-in PHP function for parsing a query string?? Have I simply overlooked something? I can do something like:

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]));
  }
}

... it just seems odd that there wouldn't be a PHP built-in to handle this. Also, I suspect I shouldn't be using htmlspecialcharacters & urldecode to scrub form-encoded values... it's a different kind of encoding, but I'm also having trouble discerning which PHP function I should be using to decode form-encoded data.

Any suggestions will be appreciated.

Was it helpful?

Solution

There's parse_str. Bad name, but does what you want. And notice that it returns nothing, the second argument is passed by reference.

OTHER TIPS

There is a function that does it - http://php.net/parse_str. Since PHP has to do this for itself, there's no reason not to also open it up for use in the API.

Parses the string into variables void parse_str ( string $str [, array &$arr])

Parses str as if it were the query string passed via a URL and sets variables in the current scope.

<?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

parse_str sucks.

parse_str is fine for simple stuff but it's not the same as PHP's built way of creating the $_GET magic variable. Why?!? I have no idea. I have developed my own version that I believe matches PHP's parsing exactly (let me know if you can find any examples that show otherwise).

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() );
}

You can use the parse_str function:

parse_str($queryString, $args);

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

parse_url will help you grab the portion of the DOCUMENT_URI that contains the actual query.

You can then pass that section off to parse_str to extract individual elements from the query.

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

I've built a simple library to parse query string to filter,sort,and select fields for my rest api. a naive version of odata . the query string transformed to object and or arrays of objects. for ex :

filters:

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

available operators 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'

to sort :

//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

for embed:

@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

easyparser

public function parseQS($queryString, &$postArray){
  parse_str($queryString, $postArray);
}

;-)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top