3

PHP automatically creates arrays in $_GET, when the parameter name is followed by [] or [keyname].

However for a public API I'd love to have the same behaviour without explicit brackets in the URL. For example, the query

?foo=bar&foo=baz

should result in a $_GET (or similar) like this:

$_GET["foo"] == array("bar", "baz");

Is there any possibility to get this behaviour in PHP easily? I.e., not parsing $_SERVER['QUERY_STRING'] myself or preg_replacing = with []= in the query string before feeding it to parse_str()?

3
  • Yes sorry, indeed, parsing it yourself it's gonna be. But it's still just one regex and a loop. Commented Jun 25, 2013 at 20:12
  • serialize the array in the url? Commented Jun 25, 2013 at 20:14
  • @Dagon I could do that, e.g., allowing foo=bar,baz and splitting on ,. But I'd like to support the basic "multiple identical query keys" method for ease of use of the API. (That's by the way the point: It should be easy to use for others.) Commented Jun 26, 2013 at 8:20

2 Answers 2

1

There's no built in way to support ?foo=bar&foo=baz.

Daniel Morell proposed a solution which manually parses the URL string and iteratively builds up an array when multiple instances of the parameter exist, or returns a string when only one parameter exists (ie; matches the default behaviour).

It supports both types of URLs, with and without a bracket:

?foo=bar&foo=baz // works
?foo[]=bar&foo[]=baz // works
/**
 * Parses GET and POST form input like $_GET and $_POST, but without requiring multiple select inputs to end the name
 * in a pair of brackets.
 * 
 * @param  string $method      The input method to use 'GET' or 'POST'.
 * @param  string $querystring A custom form input in the query string format.
 * @return array  $output      Returns an array containing the input keys and values.
 */
function bracketless_input( $method, $querystring=null ) {
    // Create empty array to 
    $output = array();
    // Get query string from function call
    if( $querystring !== null ) {
        $query = $querystring;
    // Get raw POST data
    } elseif ($method == 'POST') {
        $query = file_get_contents('php://input');
    // Get raw GET data
    } elseif ($method == 'GET') {
        $query = $_SERVER['QUERY_STRING'];
    }
    // Separerate each parameter into key value pairs
    foreach( explode( '&', $query ) as $params ) {
        $parts = explode( '=', $params );
        // Remove any existing brackets and clean up key and value
        $parts[0] = trim(preg_replace( '(\%5B|\%5D|[\[\]])', '', $parts[0] ) );
        $parts[0] = preg_replace( '([^0-9a-zA-Z])', '_', urldecode($parts[0]) );
        $parts[1] = urldecode($parts[1]);
        // Create new key in $output array if param does not exist.
        if( !key_exists( $parts[0], $output ) ) {
            $output[$parts[0]] = $parts[1];
        // Add param to array if param key already exists in $output
        } elseif( is_array( $output[$parts[0]] ) ) {
            array_push( $output[$parts[0]], $parts[1] );
        // Otherwise turn $output param into array and append current param
        } else {
            $output[$parts[0]] = array( $output[$parts[0]], $parts[1] );
        }
    }
    return $output;
}
Sign up to request clarification or add additional context in comments.

Comments

0

you can try something like this:

foreach($_GET as $slug => $value) {
#whatever you want to do, for example
print $_GET[$slug];
}

3 Comments

This will exactly once print baz. bar is completely shadowed unfortunately.
why don't you try ?foo[1]=bar&foo[2]=baz and so on. then $_GET["foo"] will be an array so you can work with it in your code.
I could do. But the use case is an API, and I want the users of the API to have using it as simply as possible. It's simple cosmetics for the URLs of the API.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.