文字

parse_str

(PHP 4, PHP 5)

parse_str将字符串解析成多个变量

说明

void parse_str ( string $str [, array &$arr ] )

如果 str 是 URL 传递入的查询字符串(query string),则将它解析为变量并设置到当前作用域。

Note:

获取当前的 QUERY_STRING,你可以使用 $_SERVER['QUERY_STRING'] 变量。 同时,你也许该阅读 来自 PHP 之外的变量 这一节。

Note:

magic_quotes_gpc 影响到了 parse_str() 这个函数的输出,和 PHP 用于填充 $_GET $_POST 及其他变量的机制一致。

参数

str

输入的字符串。

arr

如果设置了第二个变量 arr,变量将会以数组元素的形式存入到这个数组,作为替代。

返回值

没有返回值。

范例

Example #1 parse_str() 的使用

<?php
$str 
"first=value&arr[]=foo+bar&arr[]=baz" ;
parse_str ( $str );
echo 
$first ;   // value
echo  $arr [ 0 ];  // foo bar
echo  $arr [ 1 ];  // baz

parse_str ( $str $output );
echo 
$output [ 'first' ];   // value
echo  $output [ 'arr' ][ 0 ];  // foo bar
echo  $output [ 'arr' ][ 1 ];  // baz

?>

参见

  • parse_url() - 解析 URL,返回其组成部分
  • pathinfo() - 返回文件路径的信息
  • http_build_query() - 生成 URL-encode 之后的请求字符串
  • get_magic_quotes_gpc() - 获取当前 magic_quotes_gpc 的配置选项设置
  • urldecode() - 解码已编码的 URL 字符串

用户评论:

[#1] StanE [2015-09-17 21:57:23]

Note that the characters "." and " " (empty space) will be converted to "_". The characters "[" and "]" have special meaning: They represent arrays but there seems to be some weird behaviour, which I don't really understand:

<?php
// Note: "[" = %5B, "]" = %5D


parse_str("v%5D%5B=a"$r);
print_r($r);


parse_str("v%5D%5B%5B=a"$r);
print_r($r);

?>

[#2] zweibieren at yahoo dot com [2015-04-27 15:18:38]

If the arr argument is provided, all its existing elements are removed.

[#3] jmareda at seznam dot cz [2014-09-10 00:08:44]

Just remember that the array you enter will be cleared. So if you have $COOKIES variable to store cookies while crawling something, you'll have to use array_merge to merge new cookies with old ones.

[#4] markc [2013-06-30 16:43:07]

Beware using parse_str in a function that has vars passed by reference. It seems that parse_str actually creates new vars even if vars of the same name exist. If you pass by ref vars of the same name as those in a query string being parsed new LOCAL vers will be created and you won't get any values passed back to the caller (relates to what Maikel mentioned below)

An unrealistic example (vaguely related to what I was doing when I found this out)...

function get_title($query,&$title)
{
  parse_str($query);
  $title=str_replace("_"," ",$title);
}

$title="foo";
$query = "context=something&title=Title_of_Something";
get_title($query,$title);

echo $title .... "foo"

[#5] jrgns at jadeit dot co dot za [2012-06-27 08:57:37]

The array to be populated does not need to be defined before calling the function:

<?php
error_reporting
(E_ALL E_STRICT);
parse_str('var=value'$array);
?>


This will not produce a notice.

[#6] shagshag [2012-05-14 05:51:27]

That's not says in the description but max_input_vars directive affects this function. If there are more input variables on the string than specified by this directive, an E_WARNING is issued, and further input variables are truncated from the request.

[#7] Benjamin Garcia [2012-04-26 09:18:11]

function like parse_str, but doesn't convert spaces and dots to underscores in $_GET AND $_POST


function getRealREQUEST() {
$vars = array();

$input = $_SERVER['REDIRECT_QUERY_STRING'];
if(!empty($input)){
$pairs = explode("&", $input);
foreach ($pairs  as $pair) {
$nv = explode("=", $pair);

$name = urldecode($nv[0]);
$nameSanitize = preg_replace('/([^\[]*)\[.*$/','$1',$name);

$nameMatched = str_replace('.','_',$nameSanitize);
$nameMatched = str_replace(' ','_',$nameMatched);

$vars[$nameSanitize] = $_REQUEST[$nameMatched];
}
}

$input = file_get_contents("php://input");
if(!empty($input)){
$pairs = explode("&", $input);
foreach ($pairs as $pair) {
$nv = explode("=", $pair);

$name = urldecode($nv[0]);
$nameSanitize = preg_replace('/([^\[]*)\[.*$/','$1',$name);

$nameMatched = str_replace('.','_',$nameSanitize);
$nameMatched = str_replace(' ','_',$nameMatched);

$vars[$nameSanitize] = $_REQUEST[$nameMatched];
}
}

return $vars;
}

[#8] Will Voelcker [2010-08-12 11:07:50]

If you need a function that does something similar to parse_str, but doesn't convert spaces and dots to underscores, try something like the following:

<?php
function parseQueryString($str) {
    
$op = array();
    
$pairs explode("&"$str);
    foreach (
$pairs as $pair) {
        list(
$k$v) = array_map("urldecode"explode("="$pair));
        
$op[$k] = $v;
    }
    return 
$op;
}
?>


It may need adapting to handle various edge cases.

[#9] sam dot fullman at verizon dot net [2010-06-29 01:28:12]

If you're using .htaccess to spoof pages in any type of application, then $QUERY_STRING or $_SERVER['QUERY_STRING'] is going to be blank.  Instead, $_SERVER['REDIRECT_QUERY_STRING'] will hold the actual query string passed by user.  Use this function to parse this variable.

[#10] me at bubjavier dot com [2010-02-04 02:48:00]

be careful using parse_str() without the [array &$arr] parameter, as this may override values of global and existing variables.

<?php
$var1 
1;
parse_str('var1=one&var2=two');
// $var1 is now 'one'
?>


Also may lead to variable value injection when used with user input data:

<?php
$_POST
['range'] = 'min=1&max=5&important_var=important_value_no_more';

$important_var 'important_value';
parse_str($_POST['range']);
?>

[#11] tobsn at php dot net [2008-07-01 11:17:18]

just a heads up with the example above:
?var[]=123 - the [] has to be urlencoded.
var names and var values - both have to be urlencoded!

[#12] helpmepro1 at gmail dot com [2008-04-28 09:09:34]

<?php 
//by shimon doodkin

 
$url_form=url_to_form($url);
 echo 
'<form action="'.$url_form['action'].'" method="get">';
 echo 
$url_form['hidden'];
 echo 
'<input name="otherfiled" type="text">';
 echo 
'<input type="submit">';
 echo 
'</form>';

 function 
url_to_form($url)
 {
  
$url=split('\?',$url,2);
  
$action=$url[0];
  
$hidden="";
  if(isset(
$url[1]))
  {
   
$pairs=split('&',$url[1]);
   foreach(
$pairs as $pair)
   {
    
$pair=split('=',$pair,2);
    
$name=$pair[0];
    if(isset(
$pair[1]))
     
$value=$pair[1];
    else
     
$value='';
    
$name=$name;
    
$value=htmlspecialchars($value);
    if(
$name!='')
     
$hidden.='<hidden name="'.$name.'" value="'.$value.'">';
   }
  }
  return array(
'action'=>$action,'hidden'=>$hidden);
 }

?>

[#13] sean at getclicky dot com [2008-04-21 09:39:38]

This function automatically urldecodes values (not mentioned in the docs).

[#14] chris at mcfadyen dot ca [2007-11-13 16:02:59]

I shouldn't've posted the original version, as it only worked with the most basic of query strings.

This function will parse an html-safe query-like url string for variables and php-like ordered and associative arrays.  It places them into the global scope as parse_str does and adds minimal slashes for database insertions without the triple-slash problems that magic quotes can produce (the reason I had to write it in the first place).  If you don't need the slashes, they're easy enough to remove.

<?php
function parse_query($str) {
    
    
// Separate all name-value pairs
    
$pairs explode('&'$str);
    
    foreach(
$pairs as $pair) {
        
        
// Pull out the names and the values
        
list($name$value) = explode('='$pair2);
        
        
// Decode the variable name and look for arrays
        
list($name$index) = split('[][]'urldecode($name));
        
        
// Arrays
        
if(isset($index)) {
            
            
// Declare or add to the global array defined by $name
            
global $$name;
            if(!isset($
$name)) $$name = array();
            
            
// Associative array
            
if($index != "") {
                ${
$name}[$index] = addslashes(urldecode($value));
                
            
// Ordered array
            
} else {
                
array_push($$nameaddslashes(urldecode($value)));
            }
        
        
// Variables
        
} else {
            
            
// Declare or overwrite the global variable defined by $name
            
global $$name;
            $
$name addslashes(urldecode($value));
        }
    }
}
?>

[#15] chris at mcfadyen dot ca [2007-10-31 08:48:58]

If you wish a version of parse_str sans magic quotes, the following will do the trick:

<?php
function parse_query($str) {
    
$pairs explode('&'$str);

    foreach(
$pairs as $pair) {
        list(
$name$value) = explode('='$pair2);
        global $
$name;
        $
$name $value;
    }
}
?>

[#16] kermodebear at kermodebear dot org [2007-08-08 11:09:41]

An old post from several years ago mentions that variable names cannot have a dot. They also cannot have a space. Spaces are automatically replaced with an underscore.

The following:
parse_str("My Value=Something", $result);

Will result in:
$result['My_Value'] = 'Something'

Although I understand why it is done, I still feel that this is unintuitive behavior.

[#17] Evan K [2007-07-30 19:43:56]

It bears mentioning that the parse_str builtin does NOT process a query string in the CGI standard way, when it comes to duplicate fields.  If multiple fields of the same name exist in a query string, every other web processing language would read them into an array, but PHP silently overwrites them:

<?php
# silently fails to handle multiple values
parse_str('foo=1&foo=2&foo=3');

# the above produces:
$foo = array('foo' => '3');
?>


Instead, PHP uses a non-standards compliant practice of including brackets in fieldnames to achieve the same effect.

<?php
# bizarre php-specific behavior
parse_str('foo[]=1&foo[]=2&foo[]=3');

# the above produces:
$foo = array('foo' => array('1''2''3') );
?>


This can be confusing for anyone who's used to the CGI standard, so keep it in mind.  As an alternative, I use a "proper" querystring parser function:

<?php
function proper_parse_str($str) {
  
# result array
  
$arr = array();

  
# split on outer delimiter
  
$pairs explode('&'$str);

  
# loop through each pair
  
foreach ($pairs as $i) {
    
# split into name and value
    
list($name,$value) = explode('='$i2);
    
    
# if name already exists
    
if( isset($arr[$name]) ) {
      
# stick multiple values into an array
      
if( is_array($arr[$name]) ) {
        
$arr[$name][] = $value;
      }
      else {
        
$arr[$name] = array($arr[$name], $value);
      }
    }
    
# otherwise, simply stick it in a scalar
    
else {
      
$arr[$name] = $value;
    }
  }

  
# return result array
  
return $arr;
}

$query proper_parse_str($_SERVER['QUERY_STRING']);
?>

[#18] Vladimir Kornea [2007-07-17 09:04:52]

parse_str() is confused by ampersands (&) being encoded as HTML entities (&amp;). This is relevant if you're extracting your query string from an HTML page (scraping). The solution is to run the string through html_entity_decode() before running it through parse_str().

(Editors: my original comment was a caution whose solution is obvious, but it has resulted in three replies ("so what?" "as intended" and "this is how to fix it"). Please remove the previous four posts dealing with this (69529, 70234, 72745, 74818) and leave just the above summary. This issue is too trivial to warrant the number of comments it has received.)

[#19] Vladimir Kornea [2007-07-17 08:46:21]

parse_str() contained a bug (#39763) in PHP 5.2.0 that caused it to apply magic quotes twice. This bug was marked as fixed in the release notes of PHP 5.2.1, but there were apparently some issues with getting the fix through CVS on time, as our install of PHP 5.2.1 was still affected by it.

[#20] mike dot coley at inbox dot com [2007-06-02 12:25:01]

Here is a little function that does the opposite of the parse_str function. It will take an array and build a query string from it.

<?php


function append_params($array$parent='')
{
    
$params = array();
    foreach (
$array as $k => $v)
    {
        if (
is_array($v))
            
$params[] = append_params($v, (empty($parent) ? urlencode($k) : $parent '[' urlencode($k) . ']'));
        else
            
$params[] = (!empty($parent) ? $parent '[' urlencode($k) . ']' urlencode($k)) . '=' urlencode($v);
    }

    
$sessid session_id();
    if (!empty(
$parent) || empty($sessid))
        return 
implode('&'$params);

    
// Append the session ID to the query string if we have to.
    
$sessname session_name();
    if (
ini_get('session.use_cookies'))
    {
        if (!
ini_get('session.use_only_cookies') && (!isset($_COOKIE[$sessname]) || ($_COOKIE[$sessname] != $sessid)))
            
$params[] = $sessname '=' urlencode($sessid);
    }
    elseif (!
ini_get('session.use_only_cookies'))
        
$params[] = $sessname '=' urlencode($sessid);

    return 
implode('&'$params);
}

?>


Note that the function will also append the session ID to the query string if it needs to be.

[#21] Michal Zalewski [2007-04-28 11:27:45]

Vladimir Kornea:
Try use html_entity_decode()

$str = 'first=value&amp;arr[]=foo+bar&amp;arr[]=baz';
parse_str(html_entity_decode($str), $output);
print_r($output);

Array
(
    [first] => value
    [arr] => Array
        (
            [0] => foo bar
            [1] => baz
        )

)

[#22] php at voodoolabs dot net [2007-03-07 12:32:10]

This is probably a better solution than below. The first line makes sure the file doesn't exist then the second line directs all requests to a script. No need to output a 200 header with this method either.

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php      [L]

[#23] lenix.de [2007-02-10 16:20:34]

if you would like to get a nice url scheme with php/apache and and want to handle all requests in a central php script there's a simple solution/hack:

create a .htaccess in your "basedir" where you've got your main script (in this example index.php) containing some lines like:

"ErrorDocument 404 /index.php"

inside index.php you can now do

<?php
    $virtual_path 
substr(
        
$_SERVER['REQUEST_URI'],
        
strlendirname$_SERVER['PHP_SELF'] ) ) + 1
    
);
    if( (
$pos strpos$virtual_path'?' )) !== false ) {
        
parse_strsubstr$virtual_path$pos ), $_GET );
        
$_REQUEST array_merge$_REQUEST$_GET );
        
$virtual_path substr$virtual_path0$pos );
    }

    
// some code checking for a valid location, etc...
    
header'HTTP/1.1 200 OK' );
    
header'Content-Type: text/plain' );

    echo 
$virtual_path."\n\n";
    
print_r$_REQUEST );
?>


// guido 'lenix' boehm

[#24] jgbreezer at gmail dot com [2007-01-31 04:52:47]

Vladimir Kornea wrote on 8 Sep 2006:
"This function is confused by ampersands (&) being encoded as HTML entities (&amp;)"

Well, it would be - it's not supposed to be passed html entities, that's a different encoding scheme. This function does correctly decode url encoded params for you though (with the rawurlencode rather than urlencode, ie '+' is translated to a space).

[#25] Olivier Mengué [2006-10-07 14:02:09]

Vladimir: the function is OK in how it deals with &amp;.
&amp; must only be used when outputing URLs in HTML/XML data.
You should ask yourself why you have &amp; in your URL when you give it to parse_str.

[#26] Vladimir Kornea [2006-09-08 14:15:40]

This function is confused by ampersands (&) being encoded as HTML entities (&amp;).

$str = "first=value&amp;arr[]=foo+bar&amp;arr[]=baz";
parse_str($str, $output);
print_r($output);

Array
(
    [first] => value
    [amp;arr] => Array
        (
            [0] => foo bar
            [1] => baz
        )
)

[#27] PEPE_RIVAS at repixel dot net [2006-08-28 18:21:12]

CONVERT ANY FORMATTED STRING INTO VARIABLES

I developed a online payment solution for credit cards using a merchant, and this merchant returns me an answer of the state of the transaction like this:

estado=1,txnid=5555444-8454445-4455554,monto=100.00

to have all that data into variables could be fine for me! so i use str_replace(), the problem is this function recognizes each group of variables with the & character... and i have  comma separated values... so i replace comma with &

<?php
$string 
"estado=1,txnid=5555444-8454445-4455554,monto=100.00";
$string str_replace(",","&",$string);
parse_str($string);
echo 
$monto// outputs 100.00
?>

[#28] motin at demomusic dot nu [2006-04-14 18:13:13]

When you have scripts run through the command-line (like locally via cron), you might want to be able to use _GET and _POST vars. Put this in top of your scheduled task files:

<?php
    parse_str 
($_SERVER['argv'][1], $GLOBALS['_GET']);
    
parse_str ($_SERVER['argv'][2], $GLOBALS['_POST']);
?>


And call your script by:

/usr/local/bin/php /path/to/script.php "id=45&action=delete" "formsubmitted=true"

Cheers!

[#29] avi at amarcus dot com [2005-09-03 18:32:26]

If you are trying to preserve a complex array, the function serialize might be better than http_build_query or other methods of making a query string.

[#30] Tore Bj?lseth [2005-06-29 05:59:20]

As of PHP 5, you can do the exact opposite with http_build_query(). Just remember to use the optional array output parameter.

This is a very useful combination if you want to re-use a search string url, but also slightly modify it:

Example:
<?php
$url1 
"action=search&interest[]=sports&interest[]=music&sort=id";
$str parse_str($url1$output);

// Modifying criteria:
$output['sort'] = "interest";

$url2 http_build_query($output);

echo 
"<br>url1: ".$url1;
echo 
"<br>url2: ".$url2;
?>


Results in:
url1: action=search&interest[]=sports&interest[]=music&sort=id
url2: action=search&interest[0]=sports&interest[1]=music&sort=interest

(Array indexes are automatically created.)

[#31] kerosuppi [2005-05-29 09:22:43]

This does not work as expected.

<?php
class someclass
{
    var 
$query_string;
    function 
someclass($a_query_string)
    {
        
$this->query_string $a_query_string;
        
parse_str($this->query_string);
    }
    function 
output()
    {
        echo 
$this->action;
    }
}

$a_class = new someclass("action=go");
$a_class->output();
?>


Use this instead.

<?php
class someclass
{
    var 
$arr;
    function 
someclass($a_query_string)
    {
        
parse_str($a_query_string$this->arr);
    }
    function 
output()
    {
        echo 
$this->arr['action'];
    }
}

$a_class = new someclass("action=go");
$a_class->output();
?>

[#32] mortoray at ecircle-ag dot com [2005-05-25 00:18:15]

In Kent's solution you may wish to switch "urldecode" into "rawurldecode" if you'd like to get rid of the [annoying] plus '+' converted to space ' ' translation.

[#33] kent at nospam dot ioflux dot com [2005-05-06 08:13:13]

You may want to parse the query string into an array. 

<?php

function parse_query_string($url$qmark=true)
{
    if (
$qmark) {
        
$pos strpos($url"?");
        if (
$pos !== false) {
            
$url substr($url$pos 1);
        }
    }
    if (empty(
$url))
        return 
false;
    
$tokens explode("&"$url);
    
$urlVars = array();
    foreach (
$tokens as $token) {
        
$value string_pair($token"=""");
        if (
preg_match('/^([^\[]*)(\[.*\])$/'$token$matches)) {
            
parse_query_string_array($urlVars$matches[1], $matches[2], $value);
        } else {
            
$urlVars[urldecode($token)] = urldecode($value);
        }
    }
    return 
$urlVars;
}


function parse_query_string_array(&$result$k$arrayKeys$value)
{
    if (!
preg_match_all('/\[([^\]]*)\]/'$arrayKeys$matches))
        return 
$value;
    if (!isset(
$result[$k])) {
        
$result[urldecode($k)] = array();
    }
    
$temp =& $result[$k];
    
$last urldecode(array_pop($matches[1]));
    foreach (
$matches[1] as $k) {
        
$k urldecode($k);
        if (
$k === "") {
            
$temp[] = array();
            
$temp =& $temp[count($temp)-1];
        } else if (!isset(
$temp[$k])) {
            
$temp[$k] = array();
            
$temp =& $temp[$k];
        }
    }
    if (
$last === "") {
        
$temp[] = $value;
    } else {
        
$temp[urldecode($last)] = $value;
    }
}


function string_pair(&$a$delim='.'$default=false)
{
    
$n strpos($a$delim);
    if (
$n === false)
        return 
$default;
    
$result substr($a$n+strlen($delim));
    
$a substr($a0$n);
    return 
$result;
}

?>

[#34] anatilmizun at gmail dot com [2004-10-12 16:10:59]

I wrote a pair of functions using parse_str() that will write values in an array to a textfile and vice versa, read those values from the textfile back into the array. Quite useful if you need to store lots of data but don't have access to SQL.

Save the array by calling cfg_save($filename,$array) and load it back using $array=cfg_load($filename)

<?php
$newline
="?";

function 
cfg_load($cfgfile){
    global 
$newline;
    
$setting="";
    if(
file_exists($cfgfile)){
        
$setting=fopen($cfgfile"r");
        
$ookk="";
        while(
$ook=fgets($setting)){
            
#strip comment
            
$commt=strpos($ook,"##");
            if(
$commt!==false$ook=substr($ook,0,$commt);
            
#append
            
if($ook!=""$ookk=$ookk."&".    str_replace($newline,"\n",str_replace("&","%26",trim($ook)));
        }    
        
fclose($setting);    
        
parse_str($ookk$setting);
    }
    return 
$setting;
}

function 
cfg_save($cfgfile,$setting){
    global 
$intArray;
    
$intArray="";
    for(
$i=0;$i<2000;$i++)
        
$intArray[]=$i;
    if(
is_array($setting)){
        
$allkeys=array_keys($setting);
        foreach(
$allkeys as $aKey)
            
cfg_recurse($setting[$aKey], $aKey$outArray);
    }
    
$cfgf=fopen($cfgfile,"w");
    foreach(
$outArray as $aLine)
        
fputs($cfgf,stripslashes($aLine)."\r\n");
    
fclose($cfgf);
}

function 
cfg_recurse($stuffIn$keysofar, &$toAppend){
    global 
$intArray$newline;
    if(
is_array($stuffIn)){
        
$allkeys=array_keys($stuffIn);
        if(
array_slice($intArray,0,sizeof($allkeys))==$allkeys)
            
$nokey=true;
        else 
            
$nokey=false;
        foreach(
$allkeys as $aKey){
            if(!
$nokey$toKey=$aKey;    
            
cfg_recurse($stuffIn[$aKey], $keysofar."[".$toKey."]"$toAppend);
        }
    }else
        
$toAppend[]=$keysofar."=".str_replace("\n",$newline,$stuffIn);
}
?>


Note that these functions support nested arrays of unlimited levels ;)

[#35] Matt Curtis [2004-09-08 20:46:38]

If the querystring contains duplicate keys in the key-value pairs, parse_str will only return the last instance of the value.  For example, in the following:

<?php
$mystr 
"test1=blah&test2=bleh&test1=burp";
parse_str($mystr$myarray);
echo 
$myarray['test1'];
?>

The value output will be 'burp'.  

I wrote a function that takes a querystring and returns the the key-value pairs as a two-dimensional array so each duplicate key is available:

<?php
$str 
"test1=blah&test2=bleh&test1=burp";
$valsarray parse_str_ext($str);
echo 
$valsarray['test1'][0];
echo 
$valsarray['test1'][1];
echo 
$valsarray['test2'][0];

function 
parse_str_ext($toparse) {
    
$returnarray = array();
    
$keyvaluepairs split("&"$toparse);
    foreach(
$keyvaluepairs as $pairval) {
        
$splitpair split("="$pairval);
        if(!
array_key_exists($splitpair[0], $returnarray)) $returnarray[$splitpair[0]] = array();

        
$returnarray[$splitpair[0]][] = $splitpair[1];
    }
    return 
$returnarray;    
}
?>


Output will be:
blah
burp
bleh

[#36] [2004-06-17 05:23:14]

Note that variables cannot contain a DOT (.) in PHP. So, DOT will be replaced by underscore. 
e.g. variables like "variable.something" will be converted into "variable_something".

[#37] [2004-03-31 10:58:56]

The documentation does not appear to mention that parse_str also urldecodes each item in the resulting array.

There also appears to be a bug in earlier versions of PHP that causes these urldecoded strings to also be escaped.  (Certainly I was having problems with %22 being turned into /" on my server, but not on my development box, despite forcing magic quotes off).

上一篇: 下一篇: