17

I'm working with a third party API that receives several parameters which must be encoded like this:

text[]=Hello%20World&text[]=How%20are%20you?&html[]=<p>Just%20fine,%20thank%20you</p>

As you can see this API can accept multiple parameters for text, and also for HTML (not in the sample call).

I have used http_build_query to correctly build a query string for other APIs

$params['text'][] = 'Hello World';
$params['text'][] = 'How are you?';
$params['html'][] = '<p>Just fine, thank you</p>';

$http_query = http_build_query($params);

The problem with this approach is that it will build a query string with the numeric index:

text[0]=Hello%20World&text[1]=How%20are%20you?&html[0]=<p>Just%20fine,%20thank%20you</p>

unfortunately the API I'm working with doesn't like the numeric index and fails.

Is there any php function/class-method that can help me build a query like this quickly?

Thank you

4 Answers 4

13

I don't know a standard way to do it (I think there is no such way), but here's an ugly solution:

Since [] is encoded by http_build_query, you may generate string with indices and then replace them.

preg_replace('/(%5B)\d+(%5D=)/i', '$1$2', http_build_query($params));
Sign up to request clarification or add additional context in comments.

2 Comments

Idea was here, but this is the correct implementation (cf. php online manual's comments): preg_replace('/%5B[0-9]+%5D/simU', '%5B%5D', $http_query);
Agree with @ErdalG. You could also do the following: $httpQuery = http_build_query($params, null, '&'); $httpQueryDecoded = urldecode($httpQuery); $requestDataFormatted = urlencode(preg_replace('#\[[\d]+\]#', '[]', $httpQueryDecoded));
5

I very much agree with the answer by RiaD, but you might run into some problems with this code (sorry I can't just make this a comment due to lack of rep).

First off, as far as I know http_build_query returns an urlencode()'d string, which means you won't have [ and ] but instead you'll have %5B and %5D.

Second, PHP's PCRE engine recognizes the '[' character as the beginning of a character class and not just as a simple '[' (PCRE Meta Characters). This may end up replacing ALL digits from your request with '[]'.

You'll more likely want something like this:

preg_replace('/\%5B\d+\%5D/', '%5B%5D', http_build_query($params));

In this case, you'll need to escape the % characters because those also have a special meaning. Provided you have a string with the actual brackets instead of the escapes, try this:

preg_replace('/\[\d+\]/', '[]', $http_query);

Comments

4

There doesn't seem to be a way to do this with http_build_query. Sorry. On the docs page though, someone has this:

function cr_post($a,$b=0,$c=0){
    if (!is_array($a)) return false;
    foreach ((array)$a as $k=>$v){
        if ($c) $k=$b."[]"; elseif (is_int($k)) $k=$b.$k;
        if (is_array($v)||is_object($v)) {
            $r[]=cr_post($v,$k,1);continue;
        }
        $r[]=urlencode($k)."=" .urlencode($v);    
    }
    return implode("&",$r);
}


$params['text'][] = 'Hello World';
$params['text'][] = 'How are you?';
$params['html'][] = '<p>Just fine, thank you</p>';

$str = cr_post($params);
echo $str;

I haven't tested it. If it doesn't work then you're going to have to roll your own. Maybe you can publish a github gist so other people can use it!

1 Comment

I fixed the example that you posted, now it works only that it also encodes the [].
1

Try this:

$params['text'][] = 'Hello World';
$params['text'][] = 'How are you?';
$params['html'][] = '<p>Just fine, thank you</p>';
foreach ($params as $key => $value) {
    foreach ($value as $key2 => $value2) {        
        $http_query.= $key . "[]=" . $value2 . "&";
    }
}
$http_query = substr($http_query, 0, strlen($http_query)-1); // remove the last '&'
$http_query = str_replace(" ", "%20", $http_query); // manually encode spaces
echo $http_query;

3 Comments

not only spaces are encoded, it's better to use urlencode in loop
urlencode will replace [] with %5B%5D%3D - and according to the example the OP provided above - it's not the expected output.
@RiaD well, that's your solution :))))

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.