1

Introduction

So I'm trying to send form values as a query string to an API. The API expects a query string like this:

&name=Charles+Hansen&[email protected]&locations=23433&locations=23231&propertyTypes=APARTMENT&propertyTypes=TOWNHOUSE&message=test"

As you can see there are multiple "propertyTypes" and "locations" depending on how many property types or locations the user picks in the form. Because of that I have stored all $_POST data in a multidimensional array which looks like this, since I obviously can't have multiple keys with the same name "propertyTypes" or "locations":

Array
(
    [name] => Charles Hansen
    [email] => [email protected]
    [locations] => Array
        (
            [0] => 23433
            [1] => 23231
        )
    [propertyTypes] => Array
        (
            [0] => APARTMENT
            [1] => TOWNHOUSE
        )
    [message] => test
)

cURL does not support multidimensional arrays, therefore I first build the query myself before using it. This is my cURL function:

function sg_order($post_fields) {
    if($post_fields) {
        $query = http_build_query($post_fields);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, 'https://example.com/order?orgKey=' . constant('ORG_KEY'));
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
          'Content-Type: application/x-www-form-urlencoded',                 
          'Content-Length: ' . strlen($query))
        );
        $result = curl_exec($ch);

        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        if(curl_errno($ch)) {
          error_log('Curl error: ' . curl_error($ch) . $result);
        }else{
          error_log('Curl response: ' . $status);
        }
        curl_close($ch);

        return $result;
    }
}

orgKey is a required parameter for validation.

The problem

My problem is, that the query built by $query = http_build_query($post_fields); contains the keys for the nested arrays ([0], [1] etc.). The result of $query looks like this:

&name=Charles+Hansen&[email protected]&locations[0]=23433&locations[1]=23231&propertyTypes[0]=APARTMENT&propertyTypes[1]=TOWNHOUSE&message=test"

How do I get rid of the keys ([0], [1] etc.) so that the query looks exactly like what the API expects?

Additional info

  • I have no control over the API
  • I am not sending files, so a solution does not have to work with files
4
  • Conver it to json than try to send Commented Oct 25, 2019 at 10:15
  • @YasinPatel I could try that, but as far as I know their API only accepts a URL encoded string. If I send it as json, will it automatically be converted to an URL encoded string by curl, because of the HTTPHEADER setting? Commented Oct 25, 2019 at 10:20
  • 1
    If you don’t want to write your own version of http_build_query, then I’d suggest you modify php.net/manual/en/function.http-build-query.php#111819 by replacing the matches with an empty string instead of '%5B%5D'. Commented Oct 25, 2019 at 10:23
  • @04FS Yea, that works! Thanks! If you make an answer i'll accept that as a solution. Commented Oct 25, 2019 at 11:16

1 Answer 1

3

If you don’t want to write your own version of http_build_query, then I’d suggest you modify the version from this user comment in the manual, http://php.net/manual/en/function.http-build-query.php#111819

    $query = http_build_query($query);
    $query = preg_replace('/%5B[0-9]+%5D/simU', '%5B%5D', $query);

They are replacing foo[xy] with foo[] here - since you don’t want to keep the [] either, just replace '%5B%5D' in the preg_replace call with an empty string instead.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks again. Bonus question: what does "simU" in that preg_replace mean?
php.net/manual/en/reference.pcre.pattern.modifiers.php : PCRE_DOTALL (useless here IMHO), PCRE_CASELESS (useless here IMHO), PCRE_MULTILINE (useless here IMHO), PCRE_UNGREEDY (useless here IMHO). In other words, for this specific pattern, none of the modifiers is needed
@Piskvor thanks, I was typing a similar response in the meantime. The only one I can see maybe making a bit of sense here is i - if http_build_query were to erratically change its behavior one day, and return lower-case hex digits in the percent encoding of the square brackets, then %5B and %5D would still match - not sure how likely that is though. The rest of them were probably just added by whoever wrote this out of habit, I guess.
Would not match anyway, [0-9] is [0123456789], AFAIK these don't have a lower/upper case ;) Looks like habit, sure: which is why I have qualified it "for this specific pattern."
@Piskvor I was referring to the curly brackets around the number - these are URL-encoded as %5B and %5D in the return value of http_build_query, and part of the pattern. Should http_build_query decide one day to return those as %5b and %5d instead (in terms of URL-encoding, both versions are allowed), then the pattern as-is would still work with the i modifier.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.