
Late static binding (LSB) is new to PHP 5.3 (released 30 June 2009) but until recently there was a bug in how it worked with reflection. See the manual page for LSB with some examples and definition. For our example, you need to know that with class inheritance, LSB allows a static method call to be “bound to” the class from which the call originated as opposed to where the method is defined.
Consider the following:
class theFirstSelf {
const THE_CONST = 'self 1st';
static public function myConst() {
return self::THE_CONST;
}
}
class theSecondSelf extends theFirstSelf {
const THE_CONST = 'self 2nd';
}
These static calls will result as shown:
echo theFirstSelf::myConst(); // self 1st echo theSecondSelf::myConst(); // self 1st
We can invoke LSB functionality by using the keyword “static” in the place of “self”.
class theFirst {
const THE_CONST = '1st';
static public function myConst() {
return static::THE_CONST;
}
}
class theSecond extends theFirst {
const THE_CONST = '2nd';
}
Now our static calls will have different results:
echo theFirst::myConst(); // 1st echo theSecond::myConst(); // 2nd
Though fixed in PHP v3.5.9 (and further fixed for invokeArgs() in PHP v3.5.11), reflection in PHP was broken when it came to LSB.
// With ReflectionClass $rc_first = new ReflectionClass( 'theFirst' ); $rc_second = new ReflectionClass( 'theSecond' ); echo $rc_first->getMethod( 'myConst' )->invoke( null ); // 1st echo $rc_second->getMethod( 'myConst' )->invoke( null ); // 1st // and also ReflectionMethod $rm_first = new ReflectionMethod( 'theFirst', 'myConst' ); $rm_second = new ReflectionMethod( 'theSecond', 'myConst' ); echo $rm_first->invoke( null ); // 1st echo $rm_second->invoke( null ); // 1st
Obviously reflection is not needed here but this is a simple example. At times when the class or method name is unknown and given as a variable, reflection can be handy. Here, then, is a work around for those unable to upgrade to 3.5.11. We’re simply using call_user_func() to handle the invoke() cases. For a reflection method invokeArgs() replacement, call_user_func_array() can be used.
echo call_user_func( array( 'theFirst', 'myConst' ) ); // 1st echo call_user_func( array( 'theSecond', 'myConst' ) ); // 2nd
