tags:

views:

1864

answers:

5

Hiya - If I pass PHP variables with '.' in their names via $_GET PHP auto-replaces them with '_' characters. For example:

<?php
echo "url is ".$_SERVER['REQUEST_URI']."<p>";
echo "x.y is ".$_GET['x.y'].".<p>";
echo "x_y is ".$_GET['x_y'].".<p>";

... outputs the following:

url is /SpShipTool/php/testGetUrl.php?x.y=a.b
x.y is .
x_y is a.b.

... my question is this: is there any way I can get this to stop ? Cannot for the life of me figure out what I've done to deserve this :-(

PHP version I'm running with is 5.2.4-2ubuntu5.3. Thx all

A: 

I would do a preg_replace on _ and change it to .

Not the best solution by far. It really sounds like you have something misconfigured server side. Of all the times I've used get to pass a url, never had this.

Edit: Missed the part where you said you wanted the variables to have a dot.

dawnerd
Unfortunately I'm also passing in '_' characters. For my situation I'll likely have to write my own URI parser. But worth a shot - thx :-)
+4  A: 

The reason this happens is because of PHP's old register_globals functionality. The . character is not a valid character in a variable name, so PHP coverts it to an underscore in order to make sure there's compatibility.

In short, it's not a good practice to do periods in URL variables.

Jeremy Privett
It is also not a good idea to have register_globals on. In fact, it should be turned off right now if possible.
dawnerd
register_globals is in fact off, as is the default in PHP5. > The . character is not a valid character in a variable nameUnfortunately I'm not looking to use this as a variable name (I keep it as a key in the $_GET dictionary), so this 'thoughtfulness' in PHP adds no value :-(Ah well...
It doesn't matter if register_globals is on or off. PHP still performs the replacements.
Jeremy Privett
A: 

I don't think PHP variable names can contain a period.

http://us.php.net/language.variables

Variables in PHP are represented by a dollar sign followed by the name of the variable. The variable name is case-sensitive.

Variable names follow the same rules as other labels in PHP. A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'

ejunker
+9  A: 

Here's PHP.net's explanation of why it does it:

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.

That's from http://ca.php.net/variables.external.

Also, according to this comment these other characters are converted to underscores:

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)

So it looks like you're stuck with it, so you'll have to convert the underscores back to dots in your script using dawnerd's suggestion (I'd just use str_replace though.)

yjerem
+2  A: 

Long-since answered question, but there is actually a better answer (or work-around). PHP lets you at the raw input stream, so you can do something like this:

$query_string = file_get_contents('php://input');

which will give you the $_POST array in query string format, periods as they should be.

You can then parse it if you need (as per POSTer's comment)

<?php
// Function to fix up PHP's messing up POST input containing dots, etc.
function getRealPOST() {
    $pairs = explode("&", file_get_contents("php://input"));
    $vars = array();
    foreach ($pairs as $pair) {
        $nv = explode("=", $pair);
        $name = urldecode($nv[0]);
        $value = urldecode($nv[1]);
        $vars[$name] = $value;
    }
    return $vars;
}
?>

Hugely useful for OpenID parameters, which contain both '.' and '_', each with a certain meaning!

crb