According to one of the man pages http://www.php.net/manual/en/language.oop5.static.php :
Calling non-static methods statically generates an E_STRICT level warning.
But, this doesn't seem to be the case when the call is made from inside the class:
error_reporting(-1);
class Test {
private $id;
function __construct($id) { $this->id = $id; }
function id() { return $this->id; }
function __toString() {
return Test::id()
. self::id()
. static::id()
. static::id()
. call_user_func('Test::id')
. call_user_func(array('Test', 'id'));
}
}
$a = new Test('a');
$b = new Test('b');
echo "$a $b $a"; # aaaaaa bbbbbb aaaaaa
var_dump(error_get_last()); # NULL
Testing with php 5.4
DEMO: http://codepad.viper-7.com/IKp9iX
I believe I've demonstrated:
id
proves this).edit-
I'd like to add that inserting debug_backtrace() into the __toString call yields a call "type" of ->
, which means "method call".
Is this a bug, or a documented feature?
If you call a non-static function with static syntax within any class (not just the declaring class), the non-static function behaves as if it were called in the context of the current $this object.
That means that I can use methods from other class' inside my class and those methods will assume my class's $this is their class' $this. If they don't check for InstanceOf
or get_class()
they will behave exactly the same as usual.
When I say as usual I mean that they will assume that your class' $this has all the other methods and properties that their class' $this would have.
This (I think) is called object context binding. In JavaScript you have to use those call()
and/or apply()
methods to get a function to behave as if it were attached to a certain object. But in PHP it just works by using the static syntax on non-static functions.
I remember this working in C++ as well but i can't recall if it only worked if the methods belonged to inherited classes (possibly overridden methods that you want to access despite them being overridden).
Using this (hidden) feature you can implement the Decorator design pattern by which you add new functionality to an object at run-time. You can also simulate Mixins or Traits (which PHP 5.4 now supports natively) with the added bonus that this implementation is handled at run-time and as such can be done/ undone dynamically as opposed to the language feature implementation which is handled at compile time and cannot be done/ undone dynamically you have to change the code to change the feature.
I'd say it's a semi-documented feature:
In non-static contexts, the called class will be the class of the object instance. Since $this-> will try to call private methods from the same scope, using static:: may give different results. Another difference is that static:: can only refer to static properties.
In other words (as I understood), it can be used to implement late static binding: using self::id()
and static::id()
may give different results if you call them in some class that extends your Test.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With