1

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!

  • 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 Nov 15 '16 at 20:46
  • 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 Nov 15 '16 at 20:47
  • That's a fair question. The only answer I have is that I'm learning as I go. :) – Damon Nov 16 '16 at 2:43
1

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).

| improve this answer | |
  • 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 Nov 14 '16 at 18:53
  • Well, I think I'm closer, but still no luck. I've updated my question to reflect changes you have suggested. – Damon Nov 15 '16 at 5:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.