使用 PHP 和 CURL 发布多维数组

2022-08-30 10:23:27

我无法通过 CURL 将表单数据发布到位于其他主机上的接收 PHP 脚本。

我收到错误Array to string conversion

这是我发布的数组:print_r

Array
(
    [name] => Array
    (
        [0] => Jason
        [1] => Mary
        [2] => Lucy
    )
    [id] => 12
    [status] => local
    [file] => @/test.txt
)

这是发生错误的行:

curl_setopt($this->ch, CURLOPT_POSTFIELDS, $post);

第三个参数必须是数组,因为我需要将标头设置为通过同一数组发送文件,因此我无法将数组转换为查询字符串或使用。Content-Typemultipart/form-datahttp_build_query()

另外,我无法访问接收主机上的代码,因此我无法序列化和解序列化数组。

我假设名称键的值是数组是导致此错误的原因,我也假设它不支持多维数组。有没有其他方法可以解决这个问题,或者我注定要失败吗?CURLOPT_POSTFIELDS

提前致谢!


答案 1
function http_build_query_for_curl( $arrays, &$new = array(), $prefix = null ) {

    if ( is_object( $arrays ) ) {
        $arrays = get_object_vars( $arrays );
    }

    foreach ( $arrays AS $key => $value ) {
        $k = isset( $prefix ) ? $prefix . '[' . $key . ']' : $key;
        if ( is_array( $value ) OR is_object( $value )  ) {
            http_build_query_for_curl( $value, $new, $k );
        } else {
            $new[$k] = $value;
        }
    }
}

$arrays = array(
    'name' => array(
        'first' => array(
            'Natali', 'Yura'
        )
    )
);


http_build_query_for_curl( $arrays, $post );

print_r($post);

答案 2

当涉及到HTTP请求时,数组的概念并不存在。PHP(可能还有其他服务器端语言)具有内置的逻辑,可以获取看起来像数组的请求数据(对它而言),并在填充时将其作为数组放在一起,等等。$_GET$_POST

例如,当您从表单发布数组时,表单元素通常如下所示:

<form ...>
  <input name="my_array[0]">
  <input name="my_array[1]">
  <input name="my_array[2]">
</form>

甚至:

<form ...>
  <input name="my_array[]">
  <input name="my_array[]">
  <input name="my_array[]">
</form>

虽然PHP知道在接收到这些数据时如何处理这些数据(即构建一个数组),但对于HTML和HTTP,你有三个不相关的输入,它们碰巧具有相似(或相同,尽管这在技术上不是有效的HTML)名称。

若要对 cURL 请求执行相反操作,需要将数组分解为键的字符串表示形式。因此,对于您的数组,您可以执行如下操作:name

foreach ($post['name'] as $id => $name)
{
  $post['name[' . $id . ']'] = $name;
}
unset($post['name']);

这将导致您的数组看起来像:$post

Array
(
    [name[0]] => Jason
    [name[1]] => Mary
    [name[2]] => Lucy
    [id] => 12
    [status] => local
    [file] => @/test.txt
)

然后,您发布的数组中的每个键都将是一个标量值,cURL 期望该值,并且该数组将按照您需要的 HTTP 表示。