If You use php <5 You can use this. (It works fine with complex arrays.)
<?php
if (!function_exists('http_build_query')) {
function http_build_query($data, $prefix='', $sep='', $key='') {
$ret = array();
foreach ((array)$data as $k => $v) {
if (is_int($k) && $prefix != null) {
$k = urlencode($prefix . $k);
}
if ((!empty($key)) || ($key === 0)) $k = $key.'['.urlencode($k).']';
if (is_array($v) || is_object($v)) {
array_push($ret, http_build_query($v, '', $sep, $k));
} else {
array_push($ret, $k.'='.urlencode($v));
}
}
if (empty($sep)) $sep = ini_get('arg_separator.output');
return implode($sep, $ret);
}// http_build_query
}//if
?>
http_build_query
(PHP 5)
http_build_query — Generar una cadena de consulta codificada estilo URL
Descripción
Genera una cadena de consulta codificada estilo URL a partir de la matriz asociativa (o indexada) dada.
Lista de parámetros
- datos_formulario
-
Puede ser una matriz u objeto que contenga propiedades.
El formulario puede ser una estructura uni-dimensional sencilla, o una matriz de matrices (que a su vez puede contener otras matrices).
- prefijo_numerico
-
Si se usan índices numéricos en la matriz base y se provee este parámetro, éste será añadido al comienzo de los índices numéricos para aquellos elementos encontrados sólo en la matriz base.
Esto es para permitir que se opere con nombres de variables legales cuando los datos sean decodificados por PHP u otra aplicación CGI más adelante.
- separador_arg
-
arg_separator.output es usado para separar argumentos, a menos que este parámetro sea especificado, en cuyo caso éste será usado.
Valores retornados
Devuelve una cadena codificada en forma URL.
Registro de cambios
| Versión | Descripción |
|---|---|
| 5.1.2 | Se agregó el parámetro separador_arg . |
| 5.1.3 | Los corchetes cuadrados son escapados. |
Ejemplos
Example #1 Uso simple de http_build_query()
<?php
$datos = array('foo'=>'bar',
'baz'=>'boom',
'vaca'=>'leche',
'php'=>'procesador de hipertexto');
echo http_build_query($datos); // foo=bar&baz=boom&vaca=leche&php=procesador+de+hipertexto
echo http_build_query($data, '', '&'); // foo=bar&baz=boom&vaca=leche\&php=procesador+de+hipertexto
?>
Example #2 http_build_query() con elementos indexados numéricamente.
<?php
$datos = array('foo', 'bar', 'baz', 'boom', 'vaca' => 'leche',
'php' => 'procesador de hipertexto');
echo http_build_query($datos) . "\n";
echo http_build_query($datos, 'mivar_');
?>
El resultado del ejemplo seria:
0=foo&1=bar&2=baz&3=boom&vaca=leche&php=procesador+de+hipertexto mivar_0=foo&mivar_1=bar&mivar_2=baz&mivar_3=boom&vaca=leche&php=procesador+de+hipertexto
Example #3 http_build_query() con matrices complejas
<?php
$datos = array('usuario'=>array('nombre'=>'Bob Smith',
'edad'=>47,
'sexo'=>'M',
'fdm'=>'5/12/1956'),
'pasatiempos'=>array('golf', 'opera', 'poker', 'rap'),
'hijos'=>array('bobby'=>array('edad'=>12,
'sexo'=>'M'),
'sally'=>array('edad'=>8,
'sexo'=>'F')),
'CEO');
echo http_build_query($datos, 'banderas_');
?>
esto generará la salida: (acotada por razones de legibilidad)
usuario%5Bnombre%5D=Bob+Smith&usuario%5Bedad%5D=47&usuario%5Bsexo%5D=M& usuario%5Bfdm%5D=5%2F12%2F1956&pasatiempos%5B0%5D=golf&pasatiempos%5B1%5D=opera& pasatiempos%5B2%5D=poker&pasatiempos%5B3%5D=rap&hijos%5Bbobby%5D%5Bedad%5D=12& hijos%5Bbobby%5D%5Bsexo%5D=M&hijos%5Bsally%5D%5Bedad%5D=8& hijos%5Bsally%5D%5Bsexo%5D=F&banderas_0=CEO
Note: Sólo el elemento "CEO" indexado numéricamente en la matriz base recibió un prefijo. Los otros índices numéricos, encontrados bajo los pasatiempos, no requieren un prefijo tipo cadena para ser nombres legales de variables.
Example #4 Uso de http_build_query() con un objeto
<?php
class miClase {
var $foo;
var $baz;
function miClase() {
$this->foo = 'bar';
$this->baz = 'boom';
}
}
$datos = new miClase();
echo http_build_query($datos); // foo=bar&baz=boom
?>
Ver también
- parse_str() - Divide la cadena en variables
- parse_url() - Procesar una URL y devolver sus componentes
- urlencode() - Codifica como URL una cadena
- array_walk() - Aplica una función del usuario a cada elemento de una matriz.
http_build_query
22-Apr-2009 12:40
06-Aug-2008 12:33
Every encoding or escaping function needs a decoding or unescaping counterpart. The counterpart for this one is apparently parse_str().
Unfortunately, this is far from obvious from reading just this manual page, and it took me some time to find out.
I think this manual page should explicitly mention parse_str() as the decoding counterpart of http_build_query().
18-Oct-2007 06:37
Other languages (in my case Java) allow access to multiple values for the same GET/POST parameter without the use of the brace ([]) notation. I wanted to use this function because it was faster than my own PHP implementation that urlencoded each part of a parameter array, but I needed to be able to send something like this to a service:
...?q=foo&q=bar
obviously http_build_query() by itself would have given me:
...?q[0]=foo&q[1]=bar
So, preg_replace to the rescue:
...
$query_string = http_build_query($params);
$query_string = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', $query_string);
...
And I get single dimension arrays encoded how I need them. This works because the '=' character can't appear non-urlencoded except for exactly where I expect it to appear (between key / value pairs).
DISCLAIMER: this workaround was only intended for getting rid of the array notation when a parameter had multiple "simple" values. More complex structures will probably be mangled.
08-Sep-2007 08:28
This is my own version that I was using for php <=4, hope that will help someone
this can accomplish a few things:
if called w/o parameters will return the current link
if called with the first parameter like:
param1=a¶m2=b
will return a link with the query string containing ONLY what is passed.
if called with the first parameter like:
¶m1=a¶m2=b
will return a string with the current query string plus what is passed to the function
this function uses by default PHP_SELF, but if you pass the page will create the link with what you pass.
If pass secure(boolean), will create an https or http.
$url will be the actual domain. This function will use a global variable if nothing is passed, but feel free to modify it to use the _SERVER variables.
$html is a boolean. If true will create links with & else just &
<?php
function create_link($query=NULL, $page=NULL, $secure=NULL, $html=NULL, $port=NULL, $url=NULL ){
if($html === NULL) $html = true;
if($url === NULL){
if($secure==true){
$url = $GLOBALS['_cfg']['secure_site'];
} else {
$url = $GLOBALS['_cfg']['url'];
}
}
if($query === NULL) $query = $_SERVER['QUERY_STRING'];
if($port === NULL && isset($_SERVER['BIBIVU-HTTPD'])){
$port === _SERVER_ADMIN_PORT;
}
if((isset($_SERVER['BIBIVU-HTTPD']) || !isset($_COOKIE[session_name()])) && $this->is_crawler()===false){
$query = $query.($query!=''?'&':'').session_name().'='.session_id();
}
if(substr($query,0,1) == '&'){
$query = $this->change_query(substr($query,1));
}
if($page === NULL) $page = $_SERVER['PHP_SELF'];
$page = str_replace('//','/',$page);
if(substr($page,0,1)=='/') $page = substr($page,1);
$newQry = array();
if($query!=''){
parse_str($query, $newQuery);
foreach($newQuery as $key => $item){
$newQry[] = $key.'='.$item;
}
}
if($html){
//I create the URL in HTML
$query = implode('&', $newQry);
} else {
$query = implode('&', $newQry);
}
if(isset($_SERVER['BIBIVU-HTTPD'])){
$host = '';
} elseif(defined('_ADMIN_BIB') && _ADMIN_BIB==1){
if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']=='on' && ($secure===NULL || $secure===true )){
$host = 'https://';
} else {
$host = 'http://';
}
if (strrpos($_SERVER['HTTP_HOST'], ':') > 0){
$host .= substr($_SERVER['HTTP_HOST'], 0, strrpos($_SERVER['HTTP_HOST'], ':'));
} else {
$host .= $_SERVER['HTTP_HOST'];
}
} else {
if($secure==true){
$host = 'https://'.$url;
} else {
$host = 'http://'.$url;
}
}
if($port==NULL){
//check the current port used
$port = $_SERVER['SERVER_PORT'];
if($port<=0) $port = 80;
}
if($port!=80 && $port!=443){
$host .=':'.$port;
}
if($page===''){
$ret = $query;
} else {
$ret = $host.'/'.$page.($query!=''?'?'.$query:'');
}
return $ret;
}
function change_query($addto_query, $queryOld = NULL){
// change the QUERY_STRING adding or changing the value passed
if ($queryOld === NULL){
$query1 = $_SERVER['QUERY_STRING'];
} else {
$query1 = $queryOld;
}
parse_str ($query1, $array1);
parse_str ($addto_query, $array2);
$newQuery = array_merge($array1, $array2);
foreach($newQuery as $key => $item){
$newQry[] = $key . '=' . $item;
}
return implode('&', $newQry);
}
?>
27-Aug-2007 08:15
This function is wrong for http!
arrays in http is like this:
files[]=1&files[]=2&...
but function makes like this
files[0]=1&files[1]=2&...
Here is normal function:
<?php
function cr_post($a,$b=,$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);}
?>
27-Apr-2007 09:24
Be careful if you're assuming that arg_separator defaults to "&".
For me, with my xampp installation and PHP 5.2.1, this was scary:
[php.ini]
; The separator used in PHP generated URLs to separate arguments.
; Default is "&".
arg_separator.output = "&"
... as it gave me a complete headache debugging something, as I expected the string length to be the length of the string my browser was displaying. I was so certain arg_separator was "&" because I'd never changed my php.ini that it took me seemingly forever to consider looking at the source code.
D'oh.
This may seem irrelevant at first (and I realise my case is an unusual way of stumbling into this issue), but since, if you run htmlspecialchars() over "&", the result will be "&amp;", DON'T expect a one- or two-parameter http_build_query() to return a query you still have to run through htmlspecialchars().
I suggest using the third parameter to retain your sanity.
03-Feb-2007 09:27
To flyingmeteor,
Your function is pleasingly adequate, however, when comparing the results from your function with the results from the actual function, it has a minor defect. If one uses a special character (e.g. øæåöä) in a key in the $data array, it is not encoded by your function, but it is by the actual one.
This is easily solved by some minor edits:
<?php
if(!function_exists('http_build_query')) {
function http_build_query($data,$prefix=null,$sep='',$key='') {
$ret = array();
foreach((array)$data as $k => $v) {
$k = urlencode($k);
if(is_int($k) && $prefix != null) {
$k = $prefix.$k;
};
if(!empty($key)) {
$k = $key."[".$k."]";
};
if(is_array($v) || is_object($v)) {
array_push($ret,http_build_query($v,"",$sep,$k));
}
else {
array_push($ret,$k."=".urlencode($v));
};
};
if(empty($sep)) {
$sep = ini_get("arg_separator.output");
};
return implode($sep, $ret);
};
};
?>
Forgive my personal coding standard.
22-Dec-2006 11:37
I think it doesnt :( when processing array let say from MySQL db, where array is list of rows (column - value), it generates the first "row" without indexes (post_subject=xxx&post_detail=yyy) while the other rows are indexed well ( 1[post_subject]=xxx&1[post_details]=yyy )
this causes confusion when the array is read back from this string (because the first line, without index is ignored (put to another variable than rest of the array), also count of this array says n+x (N = amount of rows in the array, X = amount of columns in the first row) which is wrong. The correct way should look like
0[post_subject]=xxx&0[post_detail]=yyy
for the first entry and then to continue with the rest
11-Dec-2006 05:46
Here is another equivalent function for users that don't have PHP5 yet, it behaves the same way as the PHP5 counterpart and has one extra parameter for added functionality.
<?php
if (!function_exists('http_build_query')) {
function http_build_query($data, $prefix='', $sep='', $key='') {
$ret = array();
foreach ((array)$data as $k => $v) {
if (is_int($k) && $prefix != null) $k = urlencode($prefix . $k);
if (!empty($key)) $k = $key.'['.urlencode($k).']';
if (is_array($v) || is_object($v))
array_push($ret, http_build_query($v, '', $sep, $k));
else array_push($ret, $k.'='.urlencode($v));
}
if (empty($sep)) $sep = ini_get('arg_separator.output');
return implode($sep, $ret);
}}
?>
08-Mar-2006 03: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.
08-Mar-2006 02:25
@ xangelusx
You said that "It is actually illegal to set arg_separator.output to & ("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 & 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 & 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)
10-Jan-2006 07: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
05-Oct-2005 12: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!
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);
}
?>
29-Sep-2005 11: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);
}
}
?>
12-May-2005 01: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, "&");
}
}
?>
28-May-2004 03: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
