skip to Main Content

Is there a way to use http_build_query() without having it URL encode according to some RFC standard?

Why I don’t want to URL encode everything: I’m querying the Ebay API.. They honestly insist on parameter names not being URL encoded, as far as commas in parentheses. E.g. DomainName(0) is a parameter, and the query fails if those parens are encoded.

10

Answers


  1. Nope, it appears to always want to encode (which it should, it is meant to URL encode when building a list of params for a URL).

    You could make your own…

    $params = array('a' => 'A', 'b' => 'B');
    
    $paramsJoined = array();
    
    foreach($params as $param => $value) {
       $paramsJoined[] = "$param=$value";
    }
    
    $query = implode('&', $paramsJoined);
    

    CodePad.

    Login or Signup to reply.
  2. You might want to try their JSON API instead. I tried to get a working sample, but I don’t have an app name so I can’t verify the result. Here’s the code:

    <?php
    $appName = "Your App Name Here";
    
    $post_data = array(
      'jsonns.xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
      'jsonns.xs' => 'http://www.w3.org/2001/XMLSchema',
      'jsonns.tns' => 'http://www.ebay.com/marketplace/search/v1/services',
      'tns.findItemsByKeywordsRequest' => array(
        'keywords' => 'harry potter pheonix'
      )
    );
    
    $headers = array(
      "X-EBAY-SOA-REQUEST-DATA-FORMAT: JSON", 
      "X-EBAY-SOA-RESPONSE-DATA-FORMAT: JSON",
      "X-EBAY-SOA-OPERATION-NAME: findItemsByKeywords",
      "X-EBAY-SOA-SECURITY-APPNAME: $appName"
    );
    
    $ch = curl_init();
    
    curl_setopt($ch, CURLOPT_URL, 'http://svcs.ebay.com/services/search/FindingService/v1');
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    
    $result = curl_exec($ch);
    if($result) {
      $response = json_decode($result);
    }
    
    curl_close($ch);
    ?>
    

    You’ll need to to fill $appName with whatever the name of the app is. Also the X-EBAY-SOA-OPERATION-NAME will need to be set to the actual call, and the JSON modified if the call is different.

    Login or Signup to reply.
  3. my take on alex’s answer but is faster

    $params = array('a' => 'A', 'b' => 'B');
    $query = '';
    
    foreach ($params as $param => $value) {
       $query .= $param.'='.$value .'&';
    }
    
    echo substr($query, 0, -1);
    
    Login or Signup to reply.
  4. You can use urldecode() function on a result string which you get from http_build_query()

    Login or Signup to reply.
  5. http_build_query() is INVALID without urlencoding. Maybe you accidentally double-encode it?
    For example, try to build http query for this array:

    $params = array('a' => 'a&b=b');
    

    Without encoding, you would get

    a=a&b=b
    

    When properly encoded, you would get

    a=a%26b%3Db
    

    which is correct. If you skip encoding, be sure to avoid URL injection attacks.

    Login or Signup to reply.
  6. This could also work

    $fields = array(
        'a' => 'A', 
        'b' => 'B'
     );
    
    $separator = '';
    foreach($fields as $key=>$value) {
        $fields_string .= $separator . $key . '=' . $value; 
        $separator = '&'; 
    }
    
    Login or Signup to reply.
  7. You can use urldecode().
    Or use http_build_query with the $arg_separator argument.

        $query_data= $data = array('bar', 'baz'=>'boom');
        $numeric_prefix= 'test_';
        $arg_separator = '&';
        $http_query = http_build_query ( $query_data, $numeric_prefix, $arg_separator );
        var_dump( $http_query );
    

    the output of the above is

         string 'test_0=bar&baz=boom' (length=19)
    

    numeric_prefix: if the array indexes are numbers, this string is added as prefix in each index. In this case the ‘test_0=bar’.

    arg_separator : is used to separate arguments. If non is given php use the arg_separator.output difined in php.ini

    See php http_build_query

    Login or Signup to reply.
  8. PHP 5.3.1 (Buggy Behavior)
    http_build_query DOES escape the ‘&’ ampersand character that joins the parameters. Example: user_id=1&amp;setting_id=2.

    PHP 5.4+
    http_build_query DOES NOT escape the ‘&’ ampersand character that joins the parameters. Example: user_id=1&setting_id=2

    Example:

    $params = array(
        'user_id' => '1', 
        'setting_id' => '2'
    );
    echo http_build_query($params);
    
    // Output for PHP 5.3.1:
    user_id=1&amp;setting_id=2   // NOTICE THAT: '&' character is escaped
    
    // Output for PHP 5.4.0+:
    user_id=1&setting_id=2       // NOTICE THAT: '&' character is NOT escaped
    

    Solution when targeting multiple version

    Option #1: Write a wrapper function:

    /** 
     * This will work consistently and will never escape the '&' character
     */
    function buildQuery($params) {
        return http_build_query($params, '', '&');
    }
    

    Option #2: Ditch the http_build_query function and write your own.

    Login or Signup to reply.
  9. I tried do this recently https://gist.github.com/marcocesarato/4293986fe93139f04d8269aa3fbd47e9 the difference is that this function is array recursive and compatible with PHP4. You can manage here the urlencode

    <?php
    /**
     * Build URL query params
     * as http_build_query build a query url the difference is 
     * that this function is array recursive and compatible with PHP4
     *
     * @author Marco Cesarato <[email protected]>
     * @param $query
     * @param string $parent
     * @return string
     *
     * @example
     * $p = array('abbreviations' => array('google' => 'ggle', 'facebook' => array('abb_key' => 'fbook', 'fcbk')), 'key' => 'value');
     * echo url_build_query($p);
     */
    function url_build_query($query, $parent = null){
        $query_array = array();
        foreach($query as $key => $value){
            $_key = empty($parent) ?  urlencode($key) : $parent . '[' . urlencode($key) . ']';
            if(is_array($value)) {
                $query_array[] = url_build_query($value, $_key);
            } else {
                $query_array[] = $_key . '=' . urlencode($value);
            }
        }
        return implode('&', $query_array);
    }
    
    Login or Signup to reply.
  10. I was trying to create a GET string to attach it to the end of a url like this –

    $get_params = array(
        'include' => array(
            'enrollments',
            'current_grading_period_scores'
        ),
        'enrollment_type' => array(
            'student',
        ),
    
    );
    $get_params = http_build_query($get_params);
    $get_params = urldecode($get_params);
    $url = $domain.$slug;
    $url = $url.'?'.$get_params;
    echo $url;
    

    which prints out

    include[0]=enrollments&include[1]=current_grading_period_scores&enrollment_type[0]=student
    

    But my api didn’t like the numbers in the square brackets, so I found a regular expression that removes the numbers –

    preg_replace('/[[0-9]+]/', '[]', $get_params);
    

    The final code, and the result –

    $get_params = array(
        'include' => array(
            'enrollments',
            'current_grading_period_scores'
        ),
        'enrollment_type' => array(
            'student',
        ),
    
    );
    $get_params = http_build_query($get_params);
    $get_params = urldecode($get_params);
    $get_params = preg_replace('/[[0-9]+]/', '[]', $get_params);
    $url = $domain.$slug;
    $url = $url.'?'.$get_params;
    echo $url;
    

    Prints out –

    include[]=enrollments&include[]=current_grading_period_scores&enrollment_type[]=student

    If someone knows of a better regex let me know, I’m kind of a noob with it.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search