PHP (CI) cURL passed multidimensional array does n

2019-08-16 07:42发布

问题:

I'm having an extrange issue when receiving parameters from a POST cURL request. No matter how I encode it (json, url, rawurl, utf8, base64...) before POSTing it, I am not able to perform any decoding operation through the array elements, via loop. I'm giving you the details.

From the consuming controller, in some other php (Yii) app, I build my request like this:

private function callTheApi($options)
{
    $url = "http://api.call.com/url/api";

    $params = array(    'api_key' => $this->api_key,
                        'domain' => $this->domain,
                        'date' => $options['date'],
                        'keys' => $options['keys'] // This is an array
    );

    // Following some good advice from Daniel Vandersluis here:
    // http://stackoverflow.com/questions/3772096/posting-multidimensional-array-with-php-and-curl
    if (is_array($params['keys'])
    {
        foreach ($params['keys'] as $id => $name)
        {
            $params['keys[' . $id . ']'] = $name;
        }
        unset($params['keys']);
    }

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: multipart/form-data; charset=utf-8'));
    curl_setopt($ch, CURLOPT_TIMEOUT, 120);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, TRUE);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
    curl_setopt($ch, CURLOPT_USERAGENT, 
            "Mozilla/5.0 (Windows; U; Windows NT 5.0; en; rv:1.9.0.4) "
            . "Gecko/2009011913 Firefox/3.0.6");

    $output = curl_exec($ch);

    $error = curl_errno($ch);
    $error_text = curl_error($ch);

    curl_close($ch);

    if (!$output || $error != 0)
        die("<br><hr>Problems...<br>"
            . "Line:" . __LINE__ . " dataExtractor.php<br>"
            . "Error: " . $error . " - " . $error_text . "<hr>" 
            . $url . "<hr>");

    sleep(1);

    return json_decode($output, true);
}

And in the api itself, this is the function:

public function api()
{
    $params = $_POST;

    foreach($params as $k=>$v){
        if($k=='domain') $domain = $v;
        if($k=='date') $date = $v;
        if($k=='api_key') $api_key = $v;
        if($k=='keys') $keys = $v;
    }

    echo json_encode($keys);
    // All my logic would be here, after parsing the array correctly.
}

Ok, now for the problems:

If i leave everything like stated before, it works. I have my $keys array in the api, and I can use it however I want. The "echo json_encode($keys)" sentence returns the array ALMOST as it should be. But the problem is some values of the array are corrupted in the cURL operation. Values such as spanish characters á, é ,í, ó, ú OR ü are simply not present in the array_values.

If some key in the $keys array was spanish word "alimentación" in the original array, once it's been cURLed to the api, it becomes "alimentacin". There, the ó is not there anymore.

So, my chances are encoding each value in the array to a safely transferred value, so that I can decode it later. But what do you know, I can't.

I've tried urlencoding, rawurlencoding, json_encoding, base64_encoding... each value of the array. And if I return the received array from the api, it contains the encoded values all right. BUT.

If I loop the array in the api for decoding, and then try to return it, no matter what decoding function I'm applying to its values, the output is ALWAYS "NULL".

I have no clue what I'm doing wrong here. Not even close. So any help would be much appreciated. Thanks in advance, community.

回答1:

When you create cUrl params array you should know that keys cannot be utf8.

And when you add some parameters in foreach loop

$params['keys[' . $id . ']'] = $name;

$id can be utf8 character.

To avoid that I recommend you to use json_encode

$params = array(    
    'api_key' => $this->api_key,
    'domain' => $this->domain,
    'date' => $options['date'],
    'keys' => json_encode($options['keys']) // This is an array
);

In your api in this case you should change nothing.