php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #51176 Static calling in non-static method behaves like $this->
Submitted: 2010-03-01 16:53 UTC Modified: 2010-11-03 12:03 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:1 (50.0%)
From: majkl578 at gmail dot com Assigned: felipe (profile)
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.3.2RC3 OS: Irrelevant
Private report: No CVE-ID: None
 [2010-03-01 16:53 UTC] majkl578 at gmail dot com
Description:
------------
When calling non-existing static method from non-static method, __call() is called instead of __callStatic().
self/static/className behaves incorrectly - like $this-> in that context.

Verified on 5.3.2RC3, 5.3.1 and 5.3.0.

Reproduce code:
---------------
class Foo
{
	public function start()
	{
		self::bar();
		static::bar();
		Foo::bar();
	}
	
	public function __call($n, $a)
	{
		echo 'instance';
	}
	
	public static function __callStatic($n, $a)
	{
		echo 'static';
	}
}

$foo = new Foo();
$foo->start();

Expected result:
----------------
static
static
static

Actual result:
--------------
instance
instance
instance

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-03-02 01:17 UTC] felipe@php.net
-Status: Open +Status: Closed
 [2010-03-02 01:17 UTC] felipe@php.net
This bug has been fixed in SVN.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 [2010-03-02 13:37 UTC] majkl578 at gmail dot com
Will you backport this bugfix to PHP 5.3.2 branch?
Otherwise the behavior will be really odd due to presence of this bug.
 [2010-03-04 12:33 UTC] majkl578 at gmail dot com
Can you explain me, please, why this is not fixed in 5.3.2 stable?

"Thank you for the report, and for helping us make PHP better."
You are intentionally making PHP worse!
 [2010-03-04 14:27 UTC] felipe@php.net
Hello!
This isn't my decision, but the release manager.

Thanks.
 [2010-11-03 02:35 UTC] felipe@php.net
Automatic comment from SVN on behalf of felipe
Revision: http://svn.php.net/viewvc/?view=revision&revision=305043
Log: - Reverted fix for bug #51176
 [2010-11-03 02:45 UTC] felipe@php.net
-Status: Closed +Status: Bogus
 [2010-11-03 02:45 UTC] felipe@php.net
Hello, I've reverted the wrong changes introduced by trying to fix the issue reported, but actually there is no bug at all. self::bar(), static::bar() and foo::bar() are being called in an object context, hence the __call() is called.

I.e.
$foo->start(); // invoke the __call method
foo::start(); // invoke the __callStatic method

Thanks.
 [2010-11-03 12:03 UTC] majkl578 at gmail dot com
You cannot call foo::start(), because the method is non-static and therefore it does not make sense.

Also, self, static and class name are used to call methods statically, not in a object context.
For calling method bar in object context, I think '$this->' should be used instead.

Obviously parent should not behave this way and respect context, but I think it should be the only exception (as shown in #52713).
 [2011-05-31 02:06 UTC] david71rj at gmail dot com
Sorry by realive this topic, but I really think that it is a bug.

If I want call "bar" with context, the correct mean is $this->bar(). Else, the 
"static" sounds for me like "call without context". I'm wrong?

Please, read this topic to understand what I'm saying: 
http://stackoverflow.com/questions/6181603/php-is-handling-incorrectly-my-static-
call
 [2011-07-29 15:57 UTC] steve at twitpic dot com
This is ridiculous- this bug is not bogus, it's completely legitimate, unexpected 
behavior, and totally non documented. As a reasonable programmer, one expects a 
static call to behave the same inside of a class as well as outside of a class.

How can we bring the "desired" behavior up for vote? I think that it's insane to 
not fix it.
 [2013-08-17 13:59 UTC] daniel dot ruthardt at zoesolutions dot eu
For me, the real issue is to understand the :: operator, if you do, this is absolutely 
no bug, but consistent and wanted behaviour.

To sum it all up, the :: operator tries to call the method in the current context 
(static vs. non-static) whenever possible and assumes that the current context was 
meant for non-existing methods.

----------

In details, the :: operator, does the following:

In a non-static context:

(1) Operand 1 is the context's class (via name, static or self)
	(a) if the method is (defined) non-static, it is called non-static in the 
current context
	(b) if the method is (defined) static, it is called static
	(c) if the method is not defined and __call is defined in the context’s class, 
__call is called (in the context’s class)

(2) Operand 1 is a parent class of the context's class (via name or parent)
	(a) if the method is (defined) non-static, it is called non-static in the 
current context
	(b) if the method is (defined) static, it is called static
	(c) if the method is not defined and __call is defined in the context’s class, 
a fatal error is issued
	(d) if the method is not defined and __call is defined in the parent’s class, 
__call is called (in the parent’s class)
	(e) if the method is not defined and __call is defined in the context’s class 
and in the parent’s class, __call is called in the context’s class

(3) Operand 1 is a class not related to the context
	(a) if the method is (defined) non-static, it is called non-static in the 
current context (additionally a strict standards warning is issued)
	(b) if the method is (defined) static, it is called static
	(c) if the method is not defined and __callStatic is defined in the not related 
class, __callStatic is called (in the not related class)

Observations:

(I) 2c and 2e are inconsistent. In 2c PHP wants to handle the issue in the parent 
class, whereas in 2e suddenly the issue is handled in the context’s class. I fail to 
see consistent arguments here explaining both situations.

In a static context:

(1) Operand 1 is the context’s class (via name, static or self)
	(a) if the method is (defined) static, it is called static
	(b) if the method is (defined) non-static, it is called static (additionally a 
strict standards warning is issued)
	(c) if the method is not defined and __callStatic is defined in the context’s 
class, __callStatic is called (in the context’s class)

(2) Operand 1 is a parent class of the context’s class (via name or parent)
	(a) if the method is (defined) static, it is called static
	(b) if the method is (defined) non-static, it is called static (additionally a 
strict standards warning is issued)
	(c) if the method is not defined and __callStatic is defined in the context’s 
class, a fatal error is issued
	(d) if the method is not defined and __callStatic is defined in the parent’s 
class, __callStatic is called (in the parent’s class)
	(e) if the method is not defined and __callStatic is defined in the context’s 
and in the parent’s class, __call is called in the parent’s class

(3) Operand 1 is a class not related to the context
	(a) if the method is (defined) static, it is called static
	(b) if the method is (defined) non-static, it is called static (additionally a 
strict standards warning is issued)
	(c) if the method is not defined and __callStatic is defined in the not related 
class, __callStatic is called (in the not related class)

Observations:

(I) As compared to the non-static context, 2c and 2e are consistent.
 [2016-04-13 20:43 UTC] kak dot serpom dot po dot yaitsam at gmail dot com
This is a real badass bug. Please explain why is this behaviour considered expected?
 [2023-05-20 15:11 UTC] kusov26an at gmail dot com
Perhaps this behavior seems logical, although I don't understand why the :: operator in a non-static context should refer to non-static methods. But then answer the question: how do I call __callStatic in this context? After all, no one has provided such an opportunity
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Dec 30 14:01:28 2024 UTC