# [Bug #55311] Static methods invoke __call when called from within class

- Thread: https://externals.io/message/54244
- Original archive: https://news-web.php.net/php.internals/54244
- Started by Laruence on 2011-07-29T03:37:51+00:00
- Messages: 6
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #54244 — Laruence — 2011-07-29T03:37:51+00:00

URL: https://externals.io/message/54244#54244

Hi:
     about #55311.https://bugs.php.net/bug.php?id=55311

     I found it maybe for some reason, that somebody change the
if/elseif sequence to make this bug.

     but I am not sure about why he do this,  so I refer to maillist,  any idea?

    Index: Zend/zend_object_handlers.c
===================================================================
--- Zend/zend_object_handlers.c	(revision 313905)
+++ Zend/zend_object_handlers.c	(working copy)
@@ -988,13 +988,13 @@
 	if (!fbc && zend_hash_find(&ce->function_table, lc_function_name,
function_name_strlen+1, (void **) &fbc)==FAILURE) {
 		efree(lc_function_name);

-		if (ce->__call &&
+		if (ce->__callstatic) {
+			return zend_get_user_callstatic_function(ce, function_name_strval,
function_name_strlen);
+		} else if (ce->__call &&
 		    EG(This) &&
 		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
 		    instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
 			return zend_get_user_call_function(ce, function_name_strval,
function_name_strlen);
-		} else if (ce->__callstatic) {
-			return zend_get_user_callstatic_function(ce, function_name_strval,
function_name_strlen);
 		} else {
 	   		return NULL;
 		}
-- 
Laruence  Xinchen Hui
http://www.laruence.com/

---

## #54247 — Etienne Kneuss — 2011-07-29T08:28:21+00:00

URL: https://externals.io/message/54244#54247 · In reply to: #54244

Hi,


> Hi:
>     about #55311.https://bugs.php.net/bug.php?id=55311
>
>     I found it maybe for some reason, that somebody change the
> if/elseif sequence to make this bug.
>
>     but I am not sure about why he do this,  so I refer to maillist,  any idea?

This is not a bug.

If you call a method using the Foo::bar() syntax, you don't
necessarily get a static call.

A static call is made if either:

1) the target method is declared as static
2) There is no compatible object context at the time of the call.

In this case, it is not a static call, as the method is undeclared
(hence cannot be declared as static) and you do have a compatible
object context. So __call is used, not __callstatic.

Best,

>
>    Index: Zend/zend_object_handlers.c
> ===================================================================
> --- Zend/zend_object_handlers.c (revision 313905)
> +++ Zend/zend_object_handlers.c (working copy)
> @@ -988,13 +988,13 @@
>        if (!fbc && zend_hash_find(&ce->function_table, lc_function_name,
> function_name_strlen+1, (void **) &fbc)==FAILURE) {
>                efree(lc_function_name);
>
> -               if (ce->__call &&
> +               if (ce->__callstatic) {
> +                       return zend_get_user_callstatic_function(ce, function_name_strval,
> function_name_strlen);
> +               } else if (ce->__call &&
>                    EG(This) &&
>                    Z_OBJ_HT_P(EG(This))->get_class_entry &&
>                    instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
>                        return zend_get_user_call_function(ce, function_name_strval,
> function_name_strlen);
> -               } else if (ce->__callstatic) {
> -                       return zend_get_user_callstatic_function(ce, function_name_strval,
> function_name_strlen);
>                } else {
>                        return NULL;
>                }
> --
> Laruence  Xinchen Hui
> http://www.laruence.com/
>
> --
> 
> 
>
>



-- 
Etienne Kneuss
http://www.colder.ch

---

## #54248 — Laruence — 2011-07-29T09:10:01+00:00

URL: https://externals.io/message/54244#54248 · In reply to: #54247

Hi:

2011/7/29 Etienne Kneuss <colder@php.net>:
> Hi,
>
> 
> > […]
>
> This is not a bug.
>
> If you call a method using the Foo::bar() syntax, you don't
> necessarily get a static call.
>
> A static call is made if either:
>
> 1) the target method is declared as static
> 2) There is no compatible object context at the time of the call.

I was wondering does this is well-documented?  since when?

obviously, it is BC break to PHP 5.3.3.

in PHP 5.3.3 __staticCall is in the front of the if/elseif statements.

so I was very interesting to know why this was changed


thanks, ;)

>
> In this case, it is not a static call, as the method is undeclared
> (hence cannot be declared as static) and you do have a compatible
> object context. So __call is used, not __callstatic.
>
> Best,
>
> > […]
>
>
>
> --
> Etienne Kneuss
> http://www.colder.ch
>



-- 
Laruence  Xinchen Hui
http://www.laruence.com/

---

## #54249 — Etienne Kneuss — 2011-07-29T09:36:03+00:00

URL: https://externals.io/message/54244#54249 · In reply to: #54248

Hello,


> Hi:
>
> 2011/7/29 Etienne Kneuss <colder@php.net>:
> > […]
>
> I was wondering does this is well-documented?  since when?

It is not documented that way no, but it has always been documented
that :: can be used to access overriden members in a non-static way.
The actual rules behind static calls is a bit more general though, as
described here.

>
> obviously, it is BC break to PHP 5.3.3.
>

To me it's simply a bug fix.
Consider the following code:

class A {
   public function __call() {
       echo "__call";
   }

   public function __callStatic() {
       echo "__callStatic";
   }
}

class B extends A {
   public function test() {
      parent::test();
   }
}


$b = new B;

$b->test();

It would simply be wrong to have callStatic being called here (it
always called __call before __callStatic existed), so IMO the new
behavior is fine, and even though fixing it introduced a BC break
(like many bug fixes), it is now more consistent. Note that reverting
it again would introduce a BC break as well with current 5_3.

Best,

> in PHP 5.3.3 __staticCall is in the front of the if/elseif statements.
>
> so I was very interesting to know why this was changed
>
>
> thanks, ;)
>
> > […]
>
>
>
> --
> Laruence  Xinchen Hui
> http://www.laruence.com/
>



-- 
Etienne Kneuss
http://www.colder.ch

---

## #54250 — Laruence — 2011-07-29T09:43:57+00:00

URL: https://externals.io/message/54244#54250 · In reply to: #54249

Hi:
  hmm, this make sense,
  thanks for your explaining.

2011/7/29 Etienne Kneuss <colder@php.net>:
> Hello,
>
> 
> > […]
>
> It is not documented that way no, but it has always been documented
> that :: can be used to access overriden members in a non-static way.
> The actual rules behind static calls is a bit more general though, as
> described here.
>
> > […]
>
> To me it's simply a bug fix.
> Consider the following code:
>
> class A {
>   public function __call() {
>       echo "__call";
>   }
>
>   public function __callStatic() {
>       echo "__callStatic";
>   }
> }
>
> class B extends A {
>   public function test() {
>      parent::test();
>   }
> }
>
>
> $b = new B;
>
> $b->test();
>
> It would simply be wrong to have callStatic being called here (it
> always called __call before __callStatic existed), so IMO the new
> behavior is fine, and even though fixing it introduced a BC break
> (like many bug fixes), it is now more consistent. Note that reverting
> it again would introduce a BC break as well with current 5_3.
>
> Best,
>
> > […]
>
>
>
> --
> Etienne Kneuss
> http://www.colder.ch
>



-- 
Laruence  Xinchen Hui
http://www.laruence.com/

---

## #54251 — Felipe Pena — 2011-07-29T11:16:34+00:00

URL: https://externals.io/message/54244#54251 · In reply to: #54250

Hi,

2011/7/29 Laruence <laruence@php.net>:
> Hi:
>  hmm, this make sense,
>  thanks for your explaining.
>

Actually this behavior change was introduced in 5.3.3 [1] and reverted in 5.3.4.
I.e. the BC just happens for 5.3.3 version.


[1] - https://bugs.php.net/bug.php?id=51176

-- 
Regards,
Felipe Pena
