http_build_query

(PHP 5)

http_build_query -- Generate URL-encoded query string

Description

string http_build_query ( array formdata [, string numeric_prefix] )

Generates a URL-encoded query string from the associative (or indexed) array provided. formdata may be an array or object containing properties. A formdata array may be a simple one-dimensional structure, or an array of arrays (who in turn may contain other arrays). If numeric indices are used in the base array and a numeric_prefix is provided, it will be prepended to the numeric index for elements in the base array only. This is to allow for legal variable names when the data is decoded by PHP or another CGI application later on.

Замечание: arg_separator.output is used to separate arguments.

Пример 1. Simple usage of http_build_query()

<?php
$data
= array('foo'=>'bar',
            
'baz'=>'boom',
            
'cow'=>'milk',
            
'php'=>'hypertext processor');
            
echo
http_build_query($data); // foo=bar&baz=boom&cow=milk&php=hypertext+processor
?>

Пример 2. http_build_query() with numerically index elements.

<?php
$data
= array('foo', 'bar', 'baz', 'boom', 'cow' => 'milk', 'php' =>'hypertext processor');
            
echo
http_build_query($data);
/* Outputs:
     0=foo&1=bar&2=baz&3=boom&cow=milk&php=hypertext+processor
 */
 
echo http_build_query($data, 'myvar_');
/* Outputs:
     myvar_0=foo&myvar_1=bar&myvar_2=baz&myvar_3=boom&cow=milk&php=hypertext+processor
 */
?>

Пример 3. http_build_query() with complex arrays

<?php
$data
= array('user'=>array('name'=>'Bob Smith',
                          
'age'=>47,
                          
'sex'=>'M',
                          
'dob'=>'5/12/1956'),
            
'pastimes'=>array('golf', 'opera', 'poker', 'rap'),
            
'children'=>array('bobby'=>array('age'=>12,
                                              
'sex'=>'M'),
                              
'sally'=>array('age'=>8,
                                              
'sex'=>'F')),
            
'CEO');
                                              
echo
http_build_query($data, 'flags_');
?>

this will output : (word wrapped for readability)

user[name]=Bob+Smith&user[age]=47&user[sex]=M&user[dob]=5%1F12%1F1956&
pastimes[0]=golf&pastimes[1]=opera&pastimes[2]=poker&pastimes[3]=rap&
children[bobby][age]=12&children[bobby][sex]=M&children[sally][age]=8&
children[sally][sex]=F&flags_0=CEO

Замечание: Only the numerically indexed element in the base array "CEO" received a prefix. The other numeric indices, found under pastimes, do not require a string prefix to be legal variable names.

Пример 4. Using http_build_query() with an object

<?php
class myClass {
  var
$foo;
  var
$baz;
 
  function
myClass()
  {
  
$this->foo = 'bar';
  
$this->baz = 'boom';
  }
}

$data = new myClass();

echo
http_build_query($data); // foo=bar&baz=boom

?>

See also: parse_str(), parse_url(), urlencode(), and array_walk()



http_build_query
paulschneider at free dot fr
04-Apr-2006 11:14
using & as argument values separator produces invalid html; use &amp; instead
Colin Guthrie
08-Mar-2006 07:11
I am concerned about this function's generation of [ and ] in the variable names.

From what I can gather from http://www.faqs.org/rfcs/rfc3986.html (which I believe to be the most recent RFC on the matter), the use of square brackets is illegal here.

To be sure, always use the following:
str_replace(array('[',']'), array('%5B','%5D'), http_build_query($data));

I will also submit a bug, but thought it important to inform users.
Colin Guthrie
08-Mar-2006 06:25
@ xangelusx
You said that "It is actually illegal to set arg_separator.output to &amp; ("and amp ;") as every character is considered a seperator according to the documentation."

I don't think this is correct. arg_separator.input maybe, but not the output. How can PHP encode my URLs (that is what this setting is used for, e.g. on URL rewriting etc.) with more than one separator?  It doesn't make sence for that variable.

I have personally used &amp; as a separate for output for years in order to create valid XHTML output via PHP.

I long ago wrote a function to do this for me, but depending on where I use the output, I sometimes want &amp; and sometimes just a plain old & (think putting the value in a href="" versus using it in a Location: header). Unfortunatly, I can see no way to deprecate my function just yet, as this built in function is lacking that distinction (an optional argument would be perfect IMO)
xangelusx at hotmail dot com
26-Jan-2006 06:53
@ arjini:
  It is actually illegal to set arg_separator.output to &amp; ("and amp ;") as every character is considered a seperator according to the documentation. Hosts should only be using the single "&" (andpersand) character.

@ vlad:
  Good call checking the servers arg_separator.output setting, but note that it can contain several characters (see the default setting in php.ini). Instead, try this:

<?php
//Discover the servers preferred parameter delimiters. If empty, assume "&"
$Delims = ((ini_get("arg_separator.input") == "") ? "&" : ini_get("arg_separator.input"));
if (
strlen($Delims) > 1) {
  
$Delims = preg_split('//', $Delims, -1, PREG_SPLIT_NO_EMPTY);
} else {
  
$Delims = array($Delims);
}
$separator = $Delims[0];
?>
Ilya Rudenko
09-Jan-2006 11:57
Params with null value do not present in result string.

<?
$arr
= array('test' => null, 'test2' => 1);
echo
http_build_query($arr);
?>

will produce:

test2=1
arjini
10-Oct-2005 08:35
Note that some hosts have the ini setting "arg_separator.output" set to &amp; ("and amp ;" in case this form encoded that) and some have it set to just a plain old ampersand. When running unit tests on a number of different hosts I kept getting inconsistent results and in some cases double encoded html entitiy errors inside my url class. I changed

$queryString = http_build_query($args);

to

$queryString = html_entity_decode(http_build_query($args));

(one could change the ini setting instead but some hosts don't allow that, so this is the only catch I all solution I found).
vlad_mustafin at ukr dot net
05-Oct-2005 05:03
Dear anonymous, i think that your example is incorrect in some places (or at least is not flexible) and shortly only in names of variables (as $c, $k, etc.) and some spaces and line foldings  :), i can explain:
1. I think that next part of code is not wanted here:
<?if (!is_array($a)) return false;?>
because you have (array)$a in foreach! It is possible but not obligatory. Or maybe better to use trigger_error for this situation.
2. You don't use urlencode on key! It's wrong because it can have also unsafe value!
<?if ($c) $k=$b."[".$k."]"; elseif (is_int($k)) $k=$b.$k;?>
this part is wrong because $k can be integer even if $c is not empty. I can want to add numeric_prefix to all indexes in array, but your example will not allow to make it. Here using of elseif is excluded, these both conditions should exist simultaneously.
3. <?http_build_query($v,$k,1);?> - In my opinion it's a very rough error. You use second parameter (as "numeric_prefix" in my example and php manual for this function) for transfer of the current key into next iteration step of recursion. Certainly it's possible and is not of principle, but very not professionally, in my opinion. I use implicit rule: one ought not to violate function logic even inside of the same function one may only expand logic. And my <?http_build_query($v, null, $tmp_key);?> allows to add numeric_prefix to all indexes in array (see point 2), i need just to put $numeric_prefix instead of null into second parameter.

Also i want to extend my previous example because we must use ini_get('arg_separator.output') instead of '&' separator!

<?
if(!function_exists('http_build_query')) {
   function
http_build_query( $formdata, $numeric_prefix = null, $key = null ) {
      
$res = array();
       foreach ((array)
$formdata as $k=>$v) {
          
$tmp_key = urlencode(is_int($k) ? $numeric_prefix.$k : $k);
           if (
$key) $tmp_key = $key.'['.$tmp_key.']';
           if (
is_array($v) || is_object($v) ) {
              
$res[] = http_build_query($v, null /* or $numeric_prefix if you want to add numeric_prefix to all indexes in array*/, $tmp_key);
           } else {
              
$res[] = $tmp_key."=".urlencode($v);
           }
          
/*
           If you want, you can write this as one string:
           $res[] = ( ( is_array($v) || is_object($v) ) ? http_build_query($v, null, $tmp_key) : $tmp_key."=".urlencode($v) );
           */
      
}
      
$separator = ini_get('arg_separator.output');
       return
implode($separator, $res);
   }
}
?>

All best!
03-Oct-2005 01:33
I made my very own http_build_query function quite some time ago for php 4 and below. Works exactly like the function below; but its just a bit shorter. :P

<?
function http_build_query($a,$b='',$c=0){
if (!
is_array($a)) return false;
foreach ((array)
$a as $k=>$v){
if (
$c) $k=$b."[".$k."]"; elseif (is_int($k)) $k=$b.$k;
if (
is_array($v)||is_object($v)) {$r[]=http_build_query($v,$k,1);continue;}
$r[]=$k."=".urlencode($v);
}
return
implode("&",$r);
}
?>
vlad_mustafin at ukr dot net
29-Sep-2005 04:31
My example of this function for PHP versions < PHP5 without any regular expressions, just cycles, recursion and standard functions. It can work with complex arrays or objects or both combined.
<?php
if(!function_exists('http_build_query')) {
   function
http_build_query( $formdata, $numeric_prefix = null, $key = null ) {
      
$res = array();
       foreach ((array)
$formdata as $k=>$v) {
          
$tmp_key = urlencode(is_int($k) ? $numeric_prefix.$k : $k);
           if (
$key) {
              
$tmp_key = $key.'['.$tmp_key.']';
           }
           if (
is_array($v) || is_object($v) ) {
              
$res[] = http_build_query($v, null, $tmp_key);
           } else {
              
$res[] = $tmp_key."=".urlencode($v);
           }
       }
       return
implode("&", $res);
   }
}
?>
mauricio at elmaster dot com
27-Sep-2005 07:31
Regarding the last comment, you should use:

if(!function_exists('http_build_query'))

instead of:

if(!defined('http_build_query'))
mwwaygoo AT hotmail DOT com
08-Aug-2005 01:25
The example given below works great but not for complex arrays. So I wrote one that did :)

The 3rd and 4th parameters are used to contruct the query from the complex array, so dont use them yourself, just stick to the defined variables as defined above.

<?php
if(!defined('http_build_query'))
{
   function
http_build_query($array, $flags='', $flags_unchecked=TRUE, $index="")
   {
       if(
$flags_unchecked)
       {
           if(
is_string($flags))
           {
              
$flags = ereg_replace("[^a-z0-9_]", "", $flags);
           }
           else
           {
              
$flags = '';
           }
       }
  
      
$string = "";
       if(
is_array($array))
       {
           foreach(
$array as $name => $value)
           {
               if(
is_array($value))
               {
                   if(
$index=="")
                   {
                      
$string.=http_build_query($value, $flags, FALSE, $name);
                   }
                   else
                   {
                      
$string.=http_build_query($value, $flags, FALSE, $index."[".$name."]");
                   }
               }
               else
               {
                   if(
$index=="")
                   {
                       if(
is_int($name))
                       {
                          
$name=$flags.$name;
                       }
                      
$string .= $name . "=" . urlencode($value) . "&";
                   }
                   else
                   {
                      
$string .= $index . "[" . $name . "]=" . urlencode($value) . "&";
                   }
               }
           }
           if(
$index=="")
           {
              
$string=ereg_replace("&$","",$string);
           }
       }
       return
$string;
   }
}
?>
php dot net at hiddemann dot org
12-May-2005 06:22
This is a workaround for PHP versions < PHP5. It does not work with complex arrays, however.

<?

if (!function_exists('http_build_query')) {
   function
http_build_query($formdata, $numeric_prefix = "")
   {
      
$arr = array();
       foreach (
$formdata as $key => $val)
        
$arr[] = urlencode($numeric_prefix.$key)."=".urlencode($val);
       return
implode($arr, "&");
   }
}

?>
aidan at php dot net
27-May-2004 08:25
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat

<get_meta_tagsparse_url>
 Last updated: Tue, 15 Nov 2005