今天在写curl的时候遇到了一个问题,在post传输数据的时候,使用了http_build_query($data)方法。
$data = [ "userId" => 1, "token" => "xxxxxxxxxxx" "data" => null ] curl_setopt($ch, CURLOPT_POSTFIELDS, $this->buildQuery($data));
传到后台另一个服务的时候,竟然报错了,说我少传了data~
what?data不是明明在里面吗?
通过调查,发现http_build_query在处理空参数的时候是忽略掉的,就和没传一样
//理想 userId=1&token=xxxxxxxxxxx&data= //真实 userId=1&token=xxxxxxxxxxx
通过官方查看也没有解决方法,还有官方并不认为这是一个错误~(也对,谁让写服务的时候,这种可以为空的字段一定要传的呢~)
可木已成舟~只能想想别的方法的~
http_build_query
使用给出的关联(或下标)数组生成一个经过 URL-encode 的请求字符串。(递归变成url-encode的,有点厉害~)
解决方法:
重写一个buildQuery(),考虑到无限数组(递归解决),copy一个大佬的解决方法(稍作修改)
function buildQuery($input, $numeric_prefix = '', $arg_separator = '&', $enc_type = 2, $keyvalue_separator = '=',$prefix = '') { if ( is_array($input) || is_object($input)) { $arr = array(); foreach ( $input as $key => $value ) { $name = $prefix; if ( strlen($prefix) ) { $name .= '['.$key.']'; } else { if ( is_numeric($key) ) { $name .= $numeric_prefix; } $name .= $key; } if ( (is_array($value) || is_object($value)) && count($value) ) { $arr[] = $this->buildQuery($value,$numeric_prefix, $arg_separator,$enc_type, $keyvalue_separator,$name); } else { if ($value === null || $value === "" || ((is_array($value) || is_object($value)) && count($value) == 0)) { $value = ""; } if ((is_array($value) || is_object($value))) { print_r($value);die; } if ( $enc_type === 2 ) { $arr[] = rawurlencode($name) .$keyvalue_separator .rawurlencode($value); } else { $arr[] = urlencode($name) .$keyvalue_separator .urlencode($value); } } } return implode($arg_separator,$arr); } else { if ( $enc_type === 2 ) { return rawurlencode($input); } else { return urlencode($input); } }
使用:
$data = [ "userId" => 1, "token" => "xxxxxxxxxxx" "data" => null ] buildQuery($data); //userId=1&token=xxxxxxxxxxx&data=
完美~
ps:
http_build_query($array, null, '&', PHP_QUERY_RFC3986);
可以将空格转换成%20,而不是全是的+。
COMMENTS | NOTHING