views:

58

answers:

5

In PHP one can use variable variables...

For example...

class obj { }
$fieldName = "Surname";
$object = new obj();
$object->Name = "John";
$object->$fieldName = "Doe";
echo "{$object->Name} {$object->Surname}"; // This echoes "John Doe".

However, $fieldName string may contain some characters not allowed in variable names. PHP will still create the field with that name (much like the associative array), but I will not be able to access it with $object->...... because it would not parse correctly.

Now, is there any function that can check if the string can be used as a valid PHP variable name. If not, how would this be created using regular expressions? What are the rules for variable names in PHP?

+4  A: 

'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*' will validate a PHP variable name.

This regex is directly from the documentation at: http://www.php.net/manual/en/language.variables.basics.php

Alan Geleynse
+5  A: 

From the manual:

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]*'

So If you ran your string through the RegEx, you should be able to tell if it's valid or not.

It should be noted that the ability to access 'invalid' Object property names using a variable variable is the correct approach for some XML parsing.

For example, from the SimpleXML docs:

Accessing elements within an XML document that contain characters not permitted under PHP's naming convention (e.g. the hyphen) can be accomplished by encapsulating the element name within braces and the apostrophe.

Followed by this code example:

echo $xml->movie->{'great-lines'}->line;

So it's not necessarily wrong to have properties that can only be accessed this way.

However, if your code both creates and uses the object - one would wonder why you would use those kind of properties. Allowing, of course, a situation similar to the SimpleXML example, where an object is created to represent something outside the scope of your control.

Tim Lytle
Why does echo preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', ".1master"); prints 1? How does it accept the dot?
kornelijepetak
@kornelijepetak because `preg_match` is looking for a match, it's not validating the entire string. Use `/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/` to force the match to be the entire string.
Tim Lytle
A: 

I think regex is the way to go, and as far as I can remember the restrictions are:

  • alphanumeric
  • must start with a letter
  • can contain an underscore

so the regex would be "/[a-zA-Z]+[0-9a-zA-Z_]*/" - off the top of my head so your milage may vary.

boodle
+1  A: 

However, `$fieldName string may contain some characters not allowed in variable names. PHP will still create the field with that name (much like the associative array), but I will not be able to access it with $object->...... because it would not parse correctly.

You will still be able to access the field through the $object->{"fieldname"} syntax.

As far as I know, the only restriction is that you can't access properties with \x00 in the name and you can't define variables starting with \x00.

Example:

$a = new stdclass;
$a->{"\x00dd"} = 8; //invalid
$a->{"dd\x00dd"} = 8; //valid, but...
echo $a->{"dd\x00dd"}; //can't read (no property "dd")
Artefacto
Funny. This code actually works in PHP 4.
webbiedave
@web That's probably because null characters are used to implement private properties and they were only introduced in PHP 5.
Artefacto
+1  A: 

but I will not be able to access it with $object->...... because it would not parse correctly

but look:

class A {}

$varName = '!asd asd';
$a = new A();
$a->$varName = '1';
echo "{$a->{'!asd asd'}}"; // 1

Certainly not recommended but it can be done.

webbiedave