19

I have the problem, that PHP replaces all spaces with underscores in POST and GET variables.

For example if I have the URL: http://localhost/proxy.php?user name=Max the browser will convert it to http://localhost/proxy.php?user%20name=Max.

But if I give the $_GET parameters out, the key is not user name but user_name (note the underscore)!

Is there any possibility to change this behaviour?

TankorSmash
  • 12,186
  • 6
  • 68
  • 106
user30724
  • 225
  • 1
  • 2
  • 6
  • 1
    possible duplicate of [Get PHP to stop replacing '.' characters in $\_GET or $\_POST arrays?](http://stackoverflow.com/questions/68651/get-php-to-stop-replacing-characters-in-get-or-post-arrays) – Rok Kralj Feb 25 '15 at 16:12

4 Answers4

35

From the PHP manual:

Dots in incoming variable names

Typically, PHP does not alter the names of variables when they are passed into a script. However, it should be noted that the dot (period, full stop) is not a valid character in a PHP variable name. For the reason, look at it:

<?php $varname.ext;  /* invalid variable name */ ?>

Now, what the parser sees is a variable named $varname, followed by the string concatenation operator, followed by the barestring (i.e. unquoted string which doesn't match any known key or reserved words) 'ext'. Obviously, this doesn't have the intended result.

For this reason, it is important to note that PHP will automatically replace any dots in incoming variable names with underscores.

And a comment on the page:

The full list of field-name characters that PHP converts to _ (underscore) is the following (not just dot):

chr(32) ( ) (space)
chr(46) (.) (dot)
chr(91) ([) (open square bracket)
chr(128) - chr(159) (various)

PHP irreversibly modifies field names containing these characters in an attempt to maintain compatibility with the deprecated register_globals feature.

Charles
  • 50,943
  • 13
  • 104
  • 142
Greg
  • 316,276
  • 54
  • 369
  • 333
  • 1
    Weirdly, the editor goes into an infinite loop if I try to make the second paragraph a quote instead of code – Greg Nov 12 '08 at 12:23
  • 1
    As far as I remember square brackets are not simply substituted by underscore, but rather allow multiple values to be put into an array. – Adam Byrtek Nov 12 '08 at 12:26
  • I think it means if you have a single one, for example "hell[o". If you have a matched pair then you're correct, it will create an array. – Greg Nov 12 '08 at 12:31
  • 1
    I don't buy their argument. Correct way to do it would be to keep $_GET intact and just modify those global variable names instead. – Milan Babuškov Mar 17 '15 at 11:36
5

I think the only possibility to get the wanted parameters, is to parse them on your own using $_SERVER['QUERY_STRING']:

$a_pairs = explode('&', $_SERVER['QUERY_STRING']);
foreach($a_pairs AS $s_pair){
  $a_pair = explode('=', $s_pair);
  if(count($a_pair) == 1) $a_pair[1] = '';

  $a_pair[0] = urldecode($a_pair[0]);
  $a_pair[1] = urldecode($a_pair[1]);

  $GLOBALS['_GET'][$a_pair[0]] = $a_pair[1];
  $_GET[$a_pair[0]] = $a_pair[1];
}
Rudi
  • 61
  • 1
  • 2
  • noticed today, that "array" parameters such like "foo[0]=bar" wouldn't be interpreted as expected. – Rudi Aug 25 '11 at 14:03
  • correct, but you probably don't want that anyway, if you are expected field names that are not correct PHP variable names and will be mangled by PHP built in parsing. – Guss Apr 02 '16 at 14:12
  • For a more concise (and less side-effecty) version of Rudi's query string parser, I've wrote this: `$query=array_reduce(array_map(function($part){return array_map(function($kv){return urldecode($kv); },explode('=',$part,2));},explode('&',$_SERVER['QUERY_STRING'])),function($query,$pair){$query[$pair[0]]=@$pair[1];return $query;},[]);` (you might want to copy that out and format it properly) – Guss Apr 02 '16 at 14:20
3

In the old crazy times of register_globals query string was unpacked by PHP into global variables, but the format of variable identifiers is constrained, so obviously spaces couldn't work. This limitation remained, and honestly I believe it's a good idea to keep it this way.

If you really cannot change spaces into underscores in your URLs, just mangle the $_GET array when you process the request and substitute every underscore by a space.

Adam Byrtek
  • 12,011
  • 2
  • 32
  • 32
1

As far as i can remember, i've never seen spaces in URL parameter names...

I think, it would be better to convert all spaces of parameter names into "_".

Fred
  • 4,846
  • 1
  • 23
  • 21
  • I have the same problem with converting dots into "_". I wanted to use dots for direct matching with database table with alias table names, eg table_name.column_name. As php converts dots into "_" the string becomes un-usable "table_name_column_name". How would you solve it? – Anatoliy Aug 27 '13 at 08:03