downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

parse_url> <get_meta_tags
[edit] Last updated: Fri, 10 Feb 2012

view this page in

http_build_query

(PHP 5)

http_build_queryURL エンコードされたクエリ文字列を生成する

説明

string http_build_query ( mixed $query_data [, string $numeric_prefix [, string $arg_separator [, int $enc_type = PHP_QUERY_RFC1738 ]]] )

与えられた連想配列 (もしくは添字配列) から URL エンコードされたクエリ文字列を生成します。

パラメータ

query_data

プロパティを含む配列もしくはオブジェクト。

query_data が配列の場合の形式は、 単純な一次元構造か あるいは配列の配列 (言い換えると、他の配列を含む配列) となります。

query_data がオブジェクトの場合、 public プロパティだけが結果に含められます。

numeric_prefix

もし数値インデックスが基底となる配列に使用されたり numeric_prefix が指定された場合、 基底となる配列の要素に対する数値インデックスの前にこれが追加されます。

これは、後で PHP や他の CGI アプリケーションによってデータがデコードされる際、 正当な変数名になるよう考慮したものです。

arg_separator

arg_separator.output が区分のためのセパレータとして使用されます。ただし、 このパラメータが指定されていた場合は それが使用されます。

enc_type

デフォルトは PHP_QUERY_RFC1738 です。

enc_typePHP_QUERY_RFC1738 の場合は » RFC 1738 に従ってエンコードされ、メディアタイプは application/x-www-form-urlencoded となります。 つまり、スペースはプラス記号 (+) にエンコードされるということです。

enc_typePHP_QUERY_RFC3986 の場合は » RFC 3986 に従ってエンコードされ、 スペースはパーセント形式 (%20) となります。

返り値

URL エンコードされた文字列を返します。

変更履歴

バージョン 説明
5.4.0 enc_type パラメータが追加されました。
5.1.3 角括弧がエスケープされるようになりました。
5.1.2 パラメータ arg_separator が追加されました。

例1 http_build_query() の簡単な使用法

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

echo 
http_build_query($data) . "\n";
echo 
http_build_query($data'''&amp;');

?>

上の例の出力は以下となります。

foo=bar&baz=boom&cow=milk&php=hypertext+processor
foo=bar&amp;baz=boom&amp;cow=milk&amp;php=hypertext+processor

例2 数値インデックス要素の場合での http_build_query()

<?php
$data 
= array('foo''bar''baz''boom''cow' => 'milk''php' =>'hypertext processor');

echo 
http_build_query($data) . "\n";
echo 
http_build_query($data'myvar_');
?>

上の例の出力は以下となります。

0=foo&1=bar&2=baz&3=boom&cow=milk&php=hypertext+processor
myvar_0=foo&myvar_1=bar&myvar_2=baz&myvar_3=boom&cow=milk&php=hypertext+processor

例3 複雑な配列の場合での http_build_query()

<?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_');
?>

この例は以下を出力します: (可読性のため適宜折り返しています)

user%5Bname%5D=Bob+Smith&user%5Bage%5D=47&user%5Bsex%5D=M&
user%5Bdob%5D=5%2F12%2F1956&pastimes%5B0%5D=golf&pastimes%5B1%5D=opera&
pastimes%5B2%5D=poker&pastimes%5B3%5D=rap&children%5Bbobby%5D%5Bage%5D=12&
children%5Bbobby%5D%5Bsex%5D=M&children%5Bsally%5D%5Bage%5D=8&
children%5Bsally%5D%5Bsex%5D=F&flags_0=CEO

注意:

基底の配列内の数値インデックス要素 "CEO" のみ、 接頭辞を受け取ります。pastimes 以下にある他の数値インデックスは、 正当な変数名にするための文字列の接頭辞を要求しません。

例4 オブジェクトの場合の http_build_query() の使用

<?php
class parentClass {
    public    
$pub      'publicParent';
    protected 
$prot     'protectedParent';
    private   
$priv     'privateParent';
    public    
$pub_bar  Null;
    protected 
$prot_bar Null;
    private   
$priv_bar Null;

    public function 
__construct(){
        
$this->pub_bar  = new childClass();
        
$this->prot_bar = new childClass();
        
$this->priv_bar = new childClass();
    }
}

class 
childClass {
    public    
$pub  'publicChild';
    protected 
$prot 'protectedChild';
    private   
$priv 'privateChild';
}

$parent = new parentClass();

echo 
http_build_query($parent);
?>

上の例の出力は以下となります。

pub=publicParent&pub_bar%5Bpub%5D=publicChild

参考

  • parse_str() - 文字列を処理し、変数に代入する
  • parse_url() - URL を解釈し、その構成要素を返す
  • urlencode() - 文字列を URL エンコードする
  • array_walk() - 配列の全ての要素にユーザ関数を適用する



parse_url> <get_meta_tags
[edit] Last updated: Fri, 10 Feb 2012
 
add a note add a note User Contributed Notes http_build_query
Anonymous 08-Feb-2011 05:11
As noted before, with php5.3 the separator is &amp; on some servers it seems. Normally if posting to another php5.3 machine this will not be a problem.

But if you post to a tomcat java server or something else the &amp; might not be handled properly.

To overcome this specify:

http_build_query($array, '', '&');

and NOT

http_build_query($array); //gives &amp; to some servers
boukeversteegh at gmail dot com 31-Aug-2010 01:02
When building querystrings, you often need to pass original arguments into the new querystring. An easy way to combine a bunch of default values, plus some overwrites into a new array, is using the Array operator +. This works great with http_build_query:

<?php
   
# Suppose $_GET is set like this.
    # or put some default values in here.
   
$_GET = Array( 'page' => 'item', 'id' => 14, 'action' => 'view' );
   
   
$edit_url = http_build_query( Array( 'action' => 'edit' ) + $_GET );
   
    echo
"<a href=\"$edit_url\">Edit</a>";
   
   
/* Prints
    <a href="action=edit&page=item&id=14">Edit</a>
    */
?>
v0idnull[try_to_spam_me_now] at gee-mail dot co 11-Mar-2010 04:51
on my install of PHP 5.3, http_build_query() seems to use &amp; as the default separator. Kind of interesting when combined with stream_context_create() for a POST request, and getting $_POST['amp;fieldName'] on the receiving end.
irish [-@-] ytdj [-dot-] ca 21-Jan-2010 06:31
When using the http_build_query function to create a URL query from an array for use in something like curl_setopt($ch, CURLOPT_POSTFIELDS, $post_url), be careful about the url encoding.

In my case, I simply wanted to pass on the received $_POST data to a CURL's POST data, which requires it to be in the URL format.  If something like a space [ ] goes into the http_build_query, it comes out as a +. If you're then sending this off for POST again, you won't get the expected result.  This is good for GET but not POST.

Instead you can make your own simple function if you simply want to pass along the data:

<?php
$post_url
= '';
foreach (
$_POST AS $key=>$value)
   
$post_url .= $key.'='.$value.'&';
$post_url = rtrim($post_url, '&');
?>

You can then use this to pass along POST data in CURL.

<?php
    $ch
= curl_init($some_url);
   
curl_setopt($ch, CURLOPT_POST, true);
   
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_url);
   
curl_exec($ch);
?>

Note that at the final page that processes the POST data, you should be properly filtering/escaping it.
Edgar at goodforall dot eu 09-Sep-2009 09:01
The use of square brackets is not illegal in a url. It is meant for delimiting data, so it is probably valid to use them to represent an array index. From the RFC:  

The purpose of reserved characters is to provide a set of delimiting
characters that are distinguishable from other data within a URI.
URIs that differ in the replacement of a reserved character with its
corresponding percent-encoded octet are not equivalent.  Percent-
encoding a reserved character, or decoding a percent-encoded octet
that corresponds to a reserved character, will change how the URI is
interpreted by most applications.  Thus, characters in the reserved
set are protected from normalization and are therefore safe to be
used by scheme-specific and producer-specific algorithms for
delimiting data subcomponents within a URI.
netrox at aol dot com 26-Aug-2009 01:24
I noticed that even with the magic quotes disabled, http_build_query() automagically adds slashes to strings.

So, I had to add "stripslashes" to every string variable.
Marco K. (Germany) 21-Apr-2009 11:40
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
?>
guido dot winkelmann at pop-hannover dot net 05-Aug-2008 11: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().
donovan jimenez 18-Oct-2007 05: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.
fabrizio[AT]bibivu[DOT]com 08-Sep-2007 07: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&param2=b
will return a link with the query string containing ONLY what is passed.
if called with the first parameter like:
  &param1=a&param2=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 &amp; 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('&amp;', $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);
    }
?>
valdikss at gmail dot com 26-Aug-2007 07: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);}
?>
pinkgothic at gmail dot com 26-Apr-2007 08: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 = "&amp;"

... 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 "&amp;", the result will be "&amp;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.
mqchen at gmail dot com 03-Feb-2007 06: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.
havelka at valka dot cz 21-Dec-2006 08: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
flyingmeteor at gmail dot com 11-Dec-2006 02: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);
}}
?>
Colin Guthrie 08-Mar-2006 12: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 07-Mar-2006 11: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)
Ilya Rudenko 09-Jan-2006 04: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
vlad_mustafin at ukr dot net 04-Oct-2005 11: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 07: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 28-Sep-2005 10: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);
    }
}
?>
php dot net at hiddemann dot org 12-May-2005 12: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 02: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

 
show source | credits | stats | sitemap | contact | advertising | mirror sites