phparrayslaravelguzzleguzzle6

Guzzle post multipart request with nested array


After a long day of debugging and try and error tries searching for a good method with Guzzle6 post with nested array and resource items.

I've found on Guzzle6 documentation that data need to be post with ['multipart' => []]. This works when i got single array items. But i got nested array items like this.

[
    [firstname] => 'Danny',
    [phone] => [
        [0] => [
            [phone] => 0612345678
        ]
    ]
    [picture] => '/data/...'
]

This needs to be format as multipart for Guzzle6 as below.

[
    [
        'name' => 'firstname',
        'contents' => 'Danny'
    ],
    [
        'name' => 'phone[0][phone]
        'contents' => '0612345678'
    ],
    [
        'name' => 'picture',
        'contents' => fopen('....', 'r')
    ]
]

I want to fix this without special tricks. Is there a good way to send a post array with nested array and resource to multipart array.


Solution

  • I used @DannyBevers answer above, but discovered that it doesn't work for deeply nested arrays that need to be sent as multipart, so here is an alternative solution:

    // fake nested array to be sent multipart by guzzle
    $array = array(
            'title' => 'Test title',
            'content' => 'Test content',
            'id' => 17,
            'Post' => array(
    
                    0 => array(
                            'id' => 100027,
                            'name' => 'Fake post title',
                            'content' => 'More test content ',
                            'Comments' => array (
    
                                    0 => 'My first comment',
                                    1 => 'My second comment',
                                    2 => 'My third comment'
                            )
                    ),
                    1 => array(
                            'id' => 100028,
                            'name' => 'Another fake post title',
                            'overall' => 2,
                            'content' => 'Even More test content ',
                            'Comments' => array (
    
                                    0 => 'My other first comment',
                                    1 => 'My other second comment',
    
                            )
                    )
    
            )
    );
    
    
    $flatten = function($array, $original_key = '') use (&$flatten) {
    
        $output = [];
    
        foreach ($array as $key => $value) {
    
            $new_key = $original_key;
    
            if (empty($original_key)) {
    
                $new_key .= $key;
    
            } else {
    
                $new_key .= '[' . $key . ']';
    
            }
    
            if (is_array($value)) {
    
                $output = array_merge($output, $flatten($value, $new_key));
    
            } else {
    
                $output[$new_key] = $value;
    
            }
        }
    
        return $output;
    
    };
    
    
    $flat_array = $flatten($array);
    
    $data = [];
    
    foreach($flat_array as $key => $value) {
    
        $data[] = [
    
                'name'  => $key,
                'contents' => $value
    
        ];
    
    
    }
    
    $response = $guzzle->request($type, $get, array('multipart' => $data));