http_build_query() without url encoding

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.

113366 次浏览

不,它似乎总是想要编码(它应该这样做,它的意思是在为 URL 构建参数列表时对 URL 进行编码)。

你可以自己做..。

$params = array('a' => 'A', 'b' => 'B');


$paramsJoined = array();


foreach($params as $param => $value) {
$paramsJoined[] = "$param=$value";
}


$query = implode('&', $paramsJoined);

CodePad.

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

无论应用程序的名称是什么,你都需要用它来填充 $appName。此外,需要将 X-EBAY-SOA-OPERATION-NAME设置为实际调用,如果调用不同,则修改 JSON。

我对 Alex 的回答的看法,但是更快

$params = array('a' => 'A', 'b' => 'B');
$query = '';


foreach ($params as $param => $value) {
$query .= $param.'='.$value .'&';
}


echo substr($query, 0, -1);

可以对从 http_build_query()获得的结果字符串使用 urldecode()函数

http_build_query() is INVALID without urlencoding. Maybe you accidentally double-encode it? 例如,尝试为这个数组构建 http 查询:

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

没有编码,你会得到

a=a&b=b

如果编码正确,你会得到

a=a%26b%3Db

如果跳过编码,一定要避免 URL 注入攻击。

这样也行

$fields = array(
'a' => 'A',
'b' => 'B'
);


$separator = '';
foreach($fields as $key=>$value) {
$fields_string .= $separator . $key . '=' . $value;
$separator = '&';
}

You can use urldecode(). 或者将 http _ build _ query 与 $arg _ analysis参数一起使用。

    $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 );

以上输出为

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

Numeric _ prefix : 如果数组索引是数字,则在每个索引中添加此字符串作为前缀。在这种情况下的 Test _ 0 = bar’

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

参见 Http _ build _ query

PHP 5.3.1(Buggy Behavior) Http _ build _ query 是的转义连接参数的“ &”与符号字符。

Http _ build _ query 没有转义连接参数的“ &”与符号字符

例如:

$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

选项1: 写一个包装函式:

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

选项 # 2: 丢弃 http _ build _ query 函数并编写自己的。

我最近尝试做这个 https://gist.github.com/marcocesarato/4293986fe93139f04d8269aa3fbd47e9的区别是,这个函数是数组递归和兼容 PHP4。您可以在这里管理 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 <cesarato.developer@gmail.com>
* @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);
}

我试图创建一个 GET 字符串,将其附加到 URL 的末尾,如下所示

$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;

打印出来

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

最终代码和结果-

$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;

指纹输出

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

如果有人知道更好的正则表达式,告诉我,我是个菜鸟。