<p>You're right, this won't work— PHP doesn't know how to flatten an array into a URL param.</p>

<p>But! Guzzle has it's own way of collating multiple values for one param.</p>

<p>Basically, you build your query with Guzzle's API, then repeatedly add values to the same param with the <code>getPostFields()-&gt;add()</code> method.</p>

<pre class="lang-php prettyprint-override"><code># Note that the second argument below may need to be populated with your custom headers— but Guzzle may also take care of this when using this method…
$req = new \Guzzle\Http\Client('https://www.site.com/api/')-&gt;post('users', [], [
  'param' =&gt; 'val' # …and any other single-use keys can be set early
]);


foreach ( $selectedActivities as $option ) {
  $req-&gt;getPostFields()-&gt;add('param-name', $option-&gt;value);
}
</code></pre>

<p>I can't tell you how to visualize the URL this eventually builds, but I think the key is sending data in the body, rather than trying to manually build a query string (which still ought to work, but there are odd behaviors when duplicate params exist).</p>

CC BY-SA 3.0
2016-11-14T18:53:41.617Z
Depending on your PHP version, you may also need to wrap the constructor in parens `(new \Guzzle\Http\Client())->post(…)` because earlier versions don't allow immediately invoking a class method.
August Miller
CC BY-SA 3.0
2016-11-15T05:03:28.283Z
Well, I think I'm closer, but still no luck. I've updated my question to reflect changes you have suggested.
Damon
CC BY-SA 3.0
2016-11-14T18:49:21.473Z
2016-11-14T20:01:21.157Z
2016-11-14T20:01:21.157Z
August Miller
<p>This isn't <em>entirely</em> Craft specific, but I am using this in my plugin so I guess if I get booed out - I deserve it.</p>

<p>I am working on a plugin that makes a call to a 3rd party API. I am using Guzzle to make the post/put requests and all is working well.</p>

<p>I am struggling though, now that I want to move beyond a 1:1 parameter:value query.</p>

<p>For example, I have this:</p>

<pre><code>$client = new \Guzzle\Http\Client('http://site.com/api/');
$uri = 'users?id=' . $event-&gt;params['user']-&gt;id .
       '&amp;first_name=' . $event-&gt;params['user']-&gt;firstName .
       '&amp;last_name='  . $.event-&gt;params['user']-&gt;lastName;

$request = $client-&gt;post($uri, array('content-type' =&gt; 'application/x-www-form-urlencoded'));
$request-&gt;send();
</code></pre>

<p>So far so good.</p>

<p>Now I would like to add an "activities" parameter. Any user could have more than one activity. I am displaying them as a checkbox on my registration form - and I'm able to get the values. I am just not sure how to pass those values in my plugin to the api call.</p>

<pre><code>$activities = $event-&gt;params['user']-&gt;activity;
$selectedActivities = array();

foreach ($activities as $option) {
    if ($option-&gt;selected) {
        $selectedActivities[] = $option-&gt;value;
    }
}

error_log(print_r($selectedActivities, true));

// [0] =&gt; 2
// [1] =&gt; 3
// [2] =&gt; 4
</code></pre>

<p>Each value is the id of the activity I am passing along.</p>

<p>How does that array get passed into my existing call? This is obviously incorrect, but here is what I am trying to do:</p>

<pre><code>...
$uri = 'users?id=' . $event-&gt;params['user']-&gt;id .
       '&amp;first_name=' . $event-&gt;params['user']-&gt;firstName .
       '&amp;last_name='  . $.event-&gt;params['user']-&gt;lastName .
       '&amp;activities=' .$selectedActivities; 
...
</code></pre>

<p>I've tried using <code>serialize()</code> but I get some funky results. </p>

<p>Thank you for any suggestions!</p>

<p><strong>EDIT</strong></p>

<p>I have updated my calls accordingly - thank you for the tip!</p>

<p>I'm seeing all values come across <em>except</em> the activities array.</p>

<pre><code>$client = new \Guzzle\Http\Client('http://mysite.com/');
$uri = 'api/students?api_token=123';

$post_data = array(
    'first_name' =&gt; $event-&gt;params['user']-&gt;firstName,
    'last_name' =&gt; $event-&gt;params['user']-&gt;lastName,
    ...

  );

$request = $client-&gt;post($uri, array(
    'content-type' =&gt; 'application/json'
));

foreach ($selectedActivities as $option) {
    $request-&gt;getPostFields('activity', $option);
}

$data = json_encode($post_data);

$request-&gt;setBody($data);
$response = $request-&gt;send();
</code></pre>

<p>Everything is coming across and getting saved correctly, I'm just not seeing 'activity' in the request at all.</p>

<p>Thank you again for your help!</p>

CC BY-SA 3.0
2016-11-15T20:46:06.340Z
Check out the loop in my answer— I don't think `getPostFields` can also assign. You'll need to get the `PostFields` object with that method, then `add` each activity to it.
August Miller
CC BY-SA 3.0
2016-11-15T20:47:54.163Z
Also, if supplying JSON data in the body is an option, why not just add the `activities` as a property on that object, before encoding?
August Miller
CC BY-SA 3.0
2016-11-16T02:43:02.443Z
That's a fair question. The only answer I have is that I'm learning as I go. :)
Damon
<plugin-development>
How can I pass an array to an api call from my plugin?
# How can I pass an array to an api call from my plugin?

(Asked by: username_0 on 2016-11-14)

This isn't entirely Craft specific, but I am using this in my plugin so I guess if I get booed out - I deserve it.
I am working on a plugin that makes a call to a 3rd party API. I am using Guzzle to make the post/put requests and all is working well.
I am struggling though, now that I want to move beyond a 1:1 parameter:value query.
For example, I have this:
$client = new \Guzzle\Http\Client('http://site.com/api/');
$uri = 'users?id=' . $event->params['user']->id .
       '&first_name=' . $event->params['user']->firstName .
       '&last_name='  . $.event->params['user']->lastName;

$request = $client->post($uri, array('content-type' => 'application/x-www-form-urlencoded'));
$request->send();

So far so good.
Now I would like to add an "activities" parameter. Any user could have more than one activity. I am displaying them as a checkbox on my registration form - and I'm able to get the values. I am just not sure how to pass those values in my plugin to the api call.
$activities = $event->params['user']->activity;
$selectedActivities = array();

foreach ($activities as $option) {
    if ($option->selected) {
        $selectedActivities[] = $option->value;
    }
}

error_log(print_r($selectedActivities, true));

// [0] => 2
// [1] => 3
// [2] => 4

Each value is the id of the activity I am passing along.
How does that array get passed into my existing call? This is obviously incorrect, but here is what I am trying to do:
...
$uri = 'users?id=' . $event->params['user']->id .
       '&first_name=' . $event->params['user']->firstName .
       '&last_name='  . $.event->params['user']->lastName .
       '&activities=' .$selectedActivities; 
...

I've tried using serialize() but I get some funky results. 
Thank you for any suggestions!
EDIT
I have updated my calls accordingly - thank you for the tip!
I'm seeing all values come across except the activities array.
$client = new \Guzzle\Http\Client('http://mysite.com/');
$uri = 'api/students?api_token=123';

$post_data = array(
    'first_name' => $event->params['user']->firstName,
    'last_name' => $event->params['user']->lastName,
    ...

  );

$request = $client->post($uri, array(
    'content-type' => 'application/json'
));

foreach ($selectedActivities as $option) {
    $request->getPostFields('activity', $option);
}

$data = json_encode($post_data);

$request->setBody($data);
$response = $request->send();

Everything is coming across and getting saved correctly, I'm just not seeing 'activity' in the request at all.
Thank you again for your help!

**Tags:** plugin-development

> **Comments:**
> **username_1**: Check out the loop in my answer— I don't think `getPostFields` can also assign. You'll need to get the `PostFields` object with that method, then `add` each activity to it.  
> **username_1**: Also, if supplying JSON data in the body is an option, why not just add the `activities` as a property on that object, before encoding?  
> **username_0**: That's a fair question. The only answer I have is that I'm learning as I go. :)  

---

## 1 answers

### Answer by username_1 on 2016-11-14. Score: 1 | Accepted answer

You're right, this won't work— PHP doesn't know how to flatten an array into a URL param.
But! Guzzle has it's own way of collating multiple values for one param.
Basically, you build your query with Guzzle's API, then repeatedly add values to the same param with the getPostFields()->add() method.
# Note that the second argument below may need to be populated with your custom headers— but Guzzle may also take care of this when using this method…
$req = new \Guzzle\Http\Client('https://www.site.com/api/')->post('users', [], [
  'param' => 'val' # …and any other single-use keys can be set early
]);


foreach ( $selectedActivities as $option ) {
  $req->getPostFields()->add('param-name', $option->value);
}

I can't tell you how to visualize the URL this eventually builds, but I think the key is sending data in the body, rather than trying to manually build a query string (which still ought to work, but there are odd behaviors when duplicate params exist).

> **Comments:**
> **username_1**: Depending on your PHP version, you may also need to wrap the constructor in parens `(new \Guzzle\Http\Client())->post(…)` because earlier versions don't allow immediately invoking a class method.  
> **username_0**: Well, I think I'm closer, but still no luck. I've updated my question to reflect changes you have suggested.  

---

