PHP cURL请求中CURLOPT_POSTFIELDS只支持一维数组

sctq 2019-06-27

使用PHP发起请求时,我们会常用cURL方法,具体的PHP请求方式可以参考 PHP cURL请求详解 这篇文章。

cURL发起POST请求

在使用中,如果你需要发送POST的请求,需要配置CURLOPT_POSTCURLOPT_POSTFIELDS两个参数,curl请求封装后的源码如下:

/**
 * 使用cURL方法获取接口数据
 * @param $uri 请求的url
 * @param $param 发起POST请求时携带的参数
 * @return array 请求返回的数据,解析成json格式
 */
public function fetchApi($uri, $param = array()) {
    // 初始化curl
    $ch = curl_init($uri);
    curl_setopt_array($ch, array(
        // 不直接输出,返回到变量
        CURLOPT_RETURNTRANSFER => true,
        // 设置超时为60s,防止机器被大量超时请求卡死
        CURLOPT_TIMEOUT => 60
    ));
    // 支持POST请求
    if (!empty($param)) {
        curl_setopt_array($ch, array(
            CURLOPT_POST => true,
            // 设置POST参数
            CURLOPT_POSTFIELDS => http_build_query($param)
        ));
    }
    // 请求数据
    $data = curl_exec($ch);
    // 关闭请求
    curl_close($ch);
    // 对数据进行编码,方便前后端数据处理
    return json_decode($data);
}

POST参数

如果需要使用POST方法,你需要设置CURLOPT_POST参数为true,并在CURLOPT_POSTFIELDS中传递POST参数。

为什么使用http_build_query

需要注意的是CURLOPT_POSTFIELDS参数只支持一维数组参数,否则会出错,你可以本地测试:

为了测试这个功能,我们需要将上面的代码做一处修改:
替换行 CURLOPT_POSTFIELDS => http_build_query($param)
为:CURLOPT_POSTFIELDS => $param
// 测试发起多维数组的curl请求
public function actionTest() {
    $url = 'www.baidu.com';
    // 此处为二维关联数组
    $param = array('foo' => ['bar' => 'cow']);
    $data = $this->fetchApi($url, $param);
    echo json_encode($data);
    return $data;
}

// 结果会报错:Array to string conversion

报错信息如下图:
PHP cURL请求中CURLOPT_POSTFIELDS只支持一维数组

如果我们需要避免这种多维数组的问题,就需要使用http_build_query方法:

函数声明:

/** 函数作用:根据数组生成URL-encode之后的请求字符串
    @param $query_data 可以是数组或包含public属性的对象
    @param $numeric_prefix 如果数组是数字下标,会使用该值作为数字下标前缀
    @param $arg_separator 参数分割符,默认为&
    @param $enc_type URL编码规范
    @return string URL编码后的字符串
*/
string http_build_query ( mixed $query_data [, string $numeric_prefix [, string $arg_separator [, int $enc_type = PHP_QUERY_RFC1738 ]]] )

实例获取数据:

// 一维数组
$data = array('foo', 'bar', 'baz', 'boom', 'cow' => 'milk', 'php' =>'hypertext processor');
echo http_build_query($data) . "\n";
echo http_build_query($data, 'myvar_');
// 结果:
// 0=foo&1=bar&2=baz&3=boom&cow=milk&php=hypertext+processor
// myvar_0=foo&myvar_1=bar&myvar_2=baz&myvar_3=boom&cow=milk&php=hypertext+processor

// 多维数组
$param = array('foo' => ['bar' => 'cow']);
echo http_build_query($data);
// 结果:foo%5Bbar%5D=cow 即:foo[bar]=cow

结论:

cURL请求的POSTOPT_FIELDS只支持一维数组,如果是多维数组,需要使用http_build_query方法。但我推荐,为了请求的url规范化,应该全部使用http_build_queryPOST请求的参数进行编码。

参考资料

  1. PHP手册 CRULOPT参数:http://php.net/manual/zh/func...
  2. PHP手册 http_build_query: http://php.net/manual/zh/func...

相关推荐