Doc #62446 [Opn->Nab]: static call of non-static function breaks context of late static binding
| From: | cataphract@php.net | Date: | Fri, 29 Jun 2012 15:43:54 +0000 |
| Subject: | Doc #62446 [Opn->Nab]: static call of non-static function breaks context of late static binding | ||
| References: | 1 | Groups: | php.doc.bugs |
| Request: | Send a blank email to doc-bugs+get-8516@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=62446&edit=1
ID: 62446
Updated by: cataphract@php.net
Reported by: picht at eventit dot ag
Summary: static call of non-static function breaks context of
late static binding
-Status: Open
+Status: Not a bug
Type: Documentation Problem
Package: Documentation problem
Operating System: ubuntu 2.6.32-41-server
PHP Version: 5.3.14
Block user comment: N
Private report: N
New Comment:
I see where the confusion comes from.
'self' works because 'self' refers to the current class 'static'
refers to the 'called class'. So in
$obj = new Outer();
$obj->testWorking();
$obj->testBroken();
the first call works because 'self' refers to 'Inner'. The twist is that
'static' refers to outer. To understand this, you have to know two things:
a) In case of non static method calls, the called class is the class of the object, as I said
earlier.
b) The class of the object in the body of Inner::NonStaticCalledStaticLate() called from
Outer::testBroken() is actually outer.
b) may be surprising and is actually a nasty backwards compatibility feature of PHP. If you have
E_STRICT on you get a message like "Strict Standards: Non-static method a::bar() should not be
called statically, assuming $this from incompatible context". See also http://lxr.php.net/xref/OTHER_IMPLEMENT/hiphop-vm/doc/inconsistencies#97
In any case, this is unrelated to LSB.
Previous Comments:
------------------------------------------------------------------------
[2012-06-29 15:33:29] picht at eventit dot ag
Because the self keyword works as expected. Try and have a look at the example my
coworker posted.
------------------------------------------------------------------------
[2012-06-29 15:28:03] cataphract@php.net
I don't know where this confusion comes from. The documentation on php.net/lsb says "[I]n
case of non static method calls, [the called class] is the class of the object."
------------------------------------------------------------------------
[2012-06-29 08:15:00] kantert at eventit dot ag
This is a simpler example:
<?php
class Inner {
public static function internalStatic()
{
}
public function NonStaticCalledStaticLate()
{
static::internalStatic();
}
public function NonStaticCalledStaticSelf()
{
self::internalStatic();
}
}
class Outer {
public function testWorking()
{
Inner::NonStaticCalledStaticSelf();
}
public function testBroken()
{
Inner::NonStaticCalledStaticLate();
}
}
// Working
Inner::NonStaticCalledStaticLate();
// Working
Inner::NonStaticCalledStaticSelf();
$obj = new Outer();
// Working
$obj->testWorking();
// Broken
$obj->testBroken();
// PHP Fatal error: Call to undefined method Outer::internalStatic() in test.php on line 9
echo "Worked";
?>
------------------------------------------------------------------------
[2012-06-29 08:03:11] picht at eventit dot ag
I mixed up "Expected result" and "Actual result".
They should be the other way around. Sorry for that!
------------------------------------------------------------------------
[2012-06-29 08:00:28] picht at eventit dot ag
Description:
------------
When calling a non-static function statically the late static binding context
still points to the calling class context. This should be documented on the static
keyword page.
Test script:
---------------
<?php
class a {
public static function foo()
{
echo 'foo a';
}
public function bar()
{
// expecting to call a::foo or b::foo
// calls c::foo instead
static::foo();
}
}
class b extends a {
public static function foo()
{
echo 'foo b';
}
}
class c {
public function test()
{
b::bar();
}
public static function foo()
{
echo 'foo c';
}
}
$c = new c();
$c->test();
Expected result:
----------------
Documentation suggest b::foo will be called
Actual result:
--------------
Documentation warns about c::foo getting called
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=62446&edit=1