http_build_query() without url encoding
有没有一种方法可以使用
为什么我不想对所有内容进行URL编码:我正在查询Ebay API。.老实说,就括号中的逗号而言,他们坚持不对参数名称进行URL编码。 例如。 DomainName(0)是一个参数,如果对这些括号进行了编码,查询将失败。
您可以对从
PHP 5.3.1(Buggy行为)
http_build_query会转义连接参数的'&'和符号。示例:
PHP 5.4以上
http_build_query不会转义连接参数的'&'和符号。示例:
例:
1 2 3 4 5 6 7 8 9 10 11 | $params = array( 'user_id' => '1', 'setting_id' => '2' ); echo http_build_query($params); // Output for PHP 5.3.1: user_id=1&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 |
定位多个版本时的解决方案
选项#1:编写包装函数:
1 2 3 4 5 6 | /** * This will work consistently and will never escape the '&' character */ function buildQuery($params) { return http_build_query($params, '', '&'); } |
选项2:放弃http_build_query函数并编写自己的函数。
不,它似乎总是要进行编码(在为URL建立参数列表时应该对URL进行编码)。
你可以自己做...
1 2 3 4 5 6 7 8 9 |
键盘。
没有urlencoding的http_build_query()是无效的。也许您不小心对它进行了双重编码?
例如,尝试为该数组构建http查询:
1 |
没有编码,您将得到
1 | a=a&b=b |
正确编码后,您将获得
1 | a=a%26b%3Db |
哪个是对的。如果您跳过编码,请确保避免URL注入攻击。
您可能想尝试使用他们的JSON API。我尝试获取一个有效的示例,但是我没有应用名称,因此无法验证结果。这是代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <?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); ?> |
您需要使用应用程序的名称填充
您可以使用urldecode()。
或者使用带有$ arg_separator参数的http_build_query。
1 2 3 4 5 | $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 ); |
上面的输出是
1 | string 'test_0=bar&baz=boom' (length=19) |
numeric_prefix:如果数组索引是数字,则此字符串将作为前缀添加到每个索引中。在这种情况下," test_0 = bar"。
arg_separator:用于分隔参数。如果未指定php,请使用php.ini中定义的arg_separator.output
参见php http_build_query
我试图创建一个GET字符串,将其附加到这样的url的末尾-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | $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; |
打印出来
1 | include[0]=enrollments&include[1]=current_grading_period_scores&enrollment_type[0]=student |
但是我的api不喜欢方括号中的数字,因此我找到了删除数字的正则表达式-
1 |
最终代码和结果-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $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; |
打印输出-
如果有人知道更好的正则表达式,请告诉我,我有点菜鸟。
我最近尝试这样做https://gist.github.com/marcocesarato/4293986fe93139f04d8269aa3fbd47e9,不同之处在于该函数是数组递归的并且与PHP4兼容。您可以在此处管理urlencode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?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); } |
这也可以工作
1 2 3 4 5 6 7 8 9 10 | $fields = array( 'a' => 'A', 'b' => 'B' ); $separator = ''; foreach($fields as $key=>$value) { $fields_string .= $separator . $key . '=' . $value; $separator = '&'; } |
我对alex的回答不一,但速度更快
1 2 3 4 5 6 7 8 |