skip to Main Content

For an extern (Django) API we need to pass our GET query data to them as follow:

?products=Product1&products=Product2

So as you can see they use different encoding for arrays than the PHP inbuilt

http_build_query(['Product1', 'Product2']) => ?products[]=Product1&products[]=Product2

Is there a built in PHP way to build query to get the result the Django API expects? Or do I have to write something my self?

Thanks in advance!

2

Answers


  1. You can use code below

    $params = ['products'=>['Product1', 'Product2']];
    $query_params = http_build_query($params,null, '&');
    $query_string = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', $query_params);
    print_r($query_string);
    

    This will get query string like "products=Product1&products=Product2"

    Login or Signup to reply.
  2. That format is not supported natively.

    I think the main reason is that URL parameters are a flat key/value structure, while http_build_query() can serialise arbitrarily nested arrays and objects. To support that, you need some convention to handle data trees in a flat list. URL specs don’t provide any. PHP uses the [] notation to mimic arrays elsewhere (e.g. $_GET), so it makes sense to have such convention in the builtin query creation function.

    If you are not going to need nested data, you can easily write your own function:

    function encodeParams(array $data): string
    {
        $params = [];
        foreach ($data as $name => $val) {
            if (is_array($val)) {
                foreach ($val as $v) {
                    $params[] = sprintf('%s=%s', rawurldecode($name), rawurldecode($v));
                }
            } else {
                $params[] = sprintf('%s=%s', rawurldecode($name), rawurldecode($val));
            }
        }
        return implode('&', $params);
    }
    
    $test = [
        'products' => [
            'Product1',
            'Product2',
        ],
        'page' => 123,
        'order' => 'asc'
    ];
    
    var_dump(http_build_query($test));
    var_dump(encodeParams($test));
    
    string(68) "products%5B0%5D=Product1&products%5B1%5D=Product2&page=123&order=asc"
    string(54) "products=Product1&products=Product2&page=123&order=asc"
    

    If you’ll need nested data after all, you first have to decide what your naming convention would be.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search