How to emulate POSTing multiple checkbox form fiel

2019-05-25 04:10发布

问题:

I am using Zend_Http_Client to POST a set of data to my server running PHP. However, the server is expecting data in the form myField[], i.e. I have a set of check boxes and the user can check more than one. My current code is:

   foreach ($myValues as $value) {
    $this->client->setParameterPost('myField[]', $value);
   }

However, it seems that Zend_Http_Client is simply overwriting myField[] with the new value each time it goes through the loop. How can I add multiple POST fields of the same name using Zend_Http_Client?


UPDATE

I have actually figured out a way to do this, by hacking the Zend_Http_Client code itself. However this is not ideal. Here's how I did it:

First, I simply added the values to the POST fields like this:

$myValues = array(0,1,2);
$this->client->setParameterPost('myField', $myValues);

In the function _prepareBody(), Zend_Http_Client builds the POST data with the following code:

  $body = http_build_query($this->paramsPost, '', '&');

If you look at the POST data that it builds, it looks like this:

myField[0]=0&myField[1]=1&myField[2]=2

Of course, it is url-encoded, so it looks like this:

myField%5B0%5D=0&myField%5B1%5D=1&myField%5B2%D=2

So, I just added a preg_replace to make [0] -> [], [1] -> [], etc:

$body = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '%5B%5D=', $body);

I'd rather just use Zend_Http_Client without making changes to the library code, but this works for now. I'd be very grateful for any suggestions on how to do it without hacking the libraries.

回答1:

The simplest approach may be just to set the raw post body yourself:

$values = array(
    0,
    1,
    2,
);

$key = 'myField';
$rawData = '';
foreach ($values as $value) {
    if ($rawData !== '') {
        $rawData .= '&';
    }
    $rawData .= $key . '%5B%5D=' . $value;
}

$client = new Zend_Http_Client();
$client->setRawData($rawData);
$client->setUri('http://www.davidcaunt.co.uk/');
$client->request(Zend_Http_Client::POST);

$request = $client->getLastRequest();

//Zend_Debug::dump($request);
Zend_Debug::dump(urldecode($request));

Postdata

myField[]=0&myField[]=1&myField[]=2

If you have other variables to send in the postdata, you'll probably want to subclass Zend_Http_Client and override the implementation of _prepareBody() as follows.

This modification aims to remain compatible with future updates, and as such, calls the parent method unless POST params are set, and the form is not multipart (a file upload):

class My_Http_Client extends Zend_Http_Client
{

    function _prepareBody() 
    {
        if (count($this->paramsPost) > 0 && $this->enctype == self::ENC_URLENCODED) {
            $this->setHeaders(self::CONTENT_TYPE, self::ENC_URLENCODED);

            $body = '';
            foreach ($this->paramsPost as $key => $value) {

                if (is_array($value)) {
                    foreach ($value as $v) {
                        $body .= $key . '%5B%5D=' . $v . '&';
                    }
                } else {
                    $body .= $key . '=' . $value . '&';
                }               
            }

            return rtrim($body, '&');
        }

        return parent::_prepareBody();
    }
}

Usage

$client = new My_Http_Client();
$client->setParameterPost('name', 'John');
$client->setParameterPost('myField', array(0,1,2));
$client->setUri('http://www.davidcaunt.co.uk/');
$client->request(Zend_Http_Client::POST);

$request = $client->getLastRequest();

Zend_Debug::dump(urldecode($request));