Late Definition of PHP Class Members

Working on a class in our application, I discovered that it was being included before a number of constants it used for its members were even defined. Puzzled on how this had never been a problem I started to experiment; echoing the member at the bottom of the class file after the class closed showed the expected CONSTANT_NAME. I was very confused at runtime the value of the member in the constructor and elsewhere in the class appeared correct.

To test what all behaves in this manner I threw together this simple set of three tests including instance members, static members, and class constants.

<?php

class foo {
public $aaa = TEST_CONSTANT;
}

class bar {
static $bbb = TEST_CONSTANT;
}

class baz {
const ccc = TEST_CONSTANT;
}

define('TEST_CONSTANT', "Weird Result\n");

$x = new foo();

echo $x->aaa;
echo bar::$bbb;
echo baz::ccc;

Returns the following:

Weird Result
Weird Result
Weird Result

They all behave in the same manner, indicating that the members and class constants are not defined until the classes are invoked.

This is further demonstrated by the following example:

<?php

class foo {
public $aaa = TEST_CONSTANT;
}

$x = new foo();
echo $x->aaa;

define('TEST_CONSTANT', "Weird Result. \n");

$y = new foo();
echo $y->aaa;

Which returns:

TEST_CONSTANTTEST_CONSTANT

So by touching the foo class, its initial value for $aaa has been locked in at what TEST_CONSTANT is at that time. Some testing indicates this also stands true for static methods and class constants as well.

This is a strange behavior I wanted to draw attention to. I certainly wouldn’t try to write something that was dependent on it, although our application currently seems to be.