php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #45159 __callStatic() called only in static methods
Submitted: 2008-06-03 11:59 UTC Modified: 2008-06-04 18:40 UTC
Votes:4
Avg. Score:3.2 ± 1.5
Reproduced:4 of 4 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (25.0%)
From: reto at buxaprojects dot com Assigned:
Status: Wont fix Package: Class/Object related
PHP Version: 6CVS-2008-06-03 (snap) OS: Fedora
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2008-06-03 11:59 UTC] reto at buxaprojects dot com
Description:
------------
__call() instead of __callStatic() is called, when we call a static method from a non-static method.

Reproduce code:
---------------
abstract class One
{
	public function __call($m, $p)
	{
		echo '__call(' . $m . ') called' . "\n";
	}
	public static function __callStatic($m, $p)
	{
		echo '__callStatic(' . $m . ') called' . "\n";
	}
}
class Two extends One
{
	public function __construct()
	{
		$this->normalMethod();
		self::staticMethod();
	}
	
	private function normalMethod()
	{
		echo 'normalMethod() called' . "\n";
		parent::a();
		self::b();
		static::c();
		One::d();
		Two::e();
	}
	
	private static function staticMethod()
	{
		echo 'staticMethod() called' . "\n";
		parent::a();
		self::b();
		static::c();
		One::d();
		Two::e();
	}
}
$two = new Two();

Expected result:
----------------
normalMethod() called
__call(a) called
__callStatic(b) called
__callStatic(c) called
__callStatic(d) called
__callStatic(e) called
staticMethod() called
__callStatic(a) called
__callStatic(b) called
__callStatic(c) called
__callStatic(d) called
__callStatic(e) called


Actual result:
--------------
normalMethod() called
__call(a) called
__call(b) called
__call(c) called
__call(d) called
__call(e) called
staticMethod() called
__callStatic(a) called
__callStatic(b) called
__callStatic(c) called
__callStatic(d) called
__callStatic(e) called


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-06-03 13:10 UTC] colder@php.net
This is somewhat expected, a call to foo::bar() from a non-static context will be a non-static call, unless the function is explicitly defined as static. 

However, some of this(especially the part about calling a "static method" from/to an invalid context) is scheduled for cleanup.
 [2008-06-03 13:15 UTC] colder@php.net
Actually, in this particular case, it's completely expected.

Class A {
  public function foo() {

  }
}

class B extends A {
  public function bar() {
    parent::foo(); // normal call
    static::foo(); // normal call as well
    A::foo(); // same here...
  }
}

$b = new B; $b->bar();

Now, for BC purposes, it would probably break things if those call suddenly stop calling __call in case A::foo() wasn't defined, which how it currently works in PHP 5.
 [2008-06-03 13:42 UTC] reto at buxaprojects dot com
I see your problem that "it would probably break things". But when i'm calling a static method with static::coolMethod() i would expect that this is __always__ a static call, why using the object context when it can't be used in the static methods either?

In your example i would expect an Error that the foo() method of class A can't be called statically.
 [2008-06-03 23:41 UTC] colder@php.net
You're misunderstanding the meaning of static::foo();

it doesn't mean "call foo statically" but rather "use runtime information to get the class currently called", and do a static(or not) call to the method of that class.

It's similar to
$name = get_called_class(); $name::foo();

For more information:
php.net/language.oop5.late-static-bindings
 [2008-06-04 18:40 UTC] reto at buxaprojects dot com
ok, i see... what about the following fallback alternative for a call like A::foo()

1. if method foo() in class A exists, call it, if not -> 2
2. if method __callstatic() implemented, call it, if not -> 3
3. if method __call implemented, call it, if not -> 4
4. fatal error

and there you have compatibility for php < 5.3.

For me A::foo() looks like a static call. Or do you really think it always must follow the context? In my opinion, when calling a method in the same style from different contexts, it isn't __always__ good that they aren't treated the same...
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Wed Oct 16 17:01:27 2019 UTC