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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: reto at buxaprojects dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 22 03:01:28 2024 UTC