5

I may have just ran into one of those "wtf PHP?" moments.

According to the PHP documentation [Class member variables] are defined by using one of the keywords public, protected, or private, followed by a normal variable declaration.

I would assume this means that properties must adhere to the same naming conventions as variables. Namely, it must not start with an integer. The following code, does indeed cause a parse error:

class Foo {
    public $1st_property;
}

The documentation also states when casting arrays to an object: Arrays convert to an object with properties named by keys, and corresponding values.

So I tried

$a['1st_key'] = "Hello, World!";
$o = (object)$a;

print_r($o);

And 1st_key is indeed a property

stdClass Object
(
    [1st_key] => Hello, World!
)

Point being: The property name begins with a number, which is not a valid variable name (of course, we can access that property with $o->{'1st_key'}). But, howcome when an array is cast to an object, invalid variable names can become property names?

v0idless
  • 948
  • 2
  • 11
  • 24

2 Answers2

6

That's done by the cast. And technically spoken, those names are not invalid.

You need to differ how you can write (define) these names. If you write:

$1

That's an invalid label. But if you write

${1}

That label is not invalid.

This question might be interesting for you as well: Array to Object and Object to Array in PHP - interesting behaviour.

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
  • So you are saying something like `class Foo { public ${1}; }` would be valid? – v0idless Nov 08 '11 at 16:18
  • No, that is an invalid definition. For a normal variable like `${1}` it's a valid definition, but for `public ${1}` it's not. – hakre Nov 08 '11 at 16:32
  • Ah, okay. So we can assume the cast does what @hsz posted below. But I am still unclear as to why the latter can be done, but the parser won't allow the former. They both accomplish the same task. – v0idless Nov 08 '11 at 16:40
  • 1
    That's a matter of the PHP parser, it differs between both cases. That might seem inconsistent, however, it is like it is, hence the parse error. hsz example uses the runtime to set the property, that's not a real definition in code, it's one at runtime. If you would use the `ReflectionClass` on Foo, it does not show up as property, the `ReflectionObject` on an object of it, will. – hakre Nov 08 '11 at 16:43
1

You are right - there is no possibility to create an invalid property like:

class Foo {
    public $1st_property;
}

But you can do:

class Foo {
    function __construct() {
        $this->{'1st_property'} = 'default value';
    }

    function get1st_property() {
        return $this->{'1st_property'};
    }

    function set1st_property($value) {
        $this->{'1st_property'} = $value;
    }
}
hsz
  • 148,279
  • 62
  • 259
  • 315
  • But why? As your second example shows, properties can begin with numbers. Is it just tricking the parser into doing something its not suppose to do? – v0idless Nov 08 '11 at 16:02