__call interceptor and static methods

php.internals

Timm Friebe

21 years ago
Hi, is there any reason why __call shouldn't be invoked for static method calls? Reproduce --------- php5 -r 'class A { function __call($name, $args) { var_dump($name, $args); } } A::foo();' Actual result ------------- Fatal error: Call to undefined method A::foo() in Command line code on line 1 Expected result --------------- string(3) "foo" array(0) { } - Timm

Sebastian Bergmann

21 years ago
Timm Friebe wrote:
> is there any reason why __call shouldn't be invoked for static method > calls?
None that I can think of. If it is doable it should be supported.
-- Sebastian Bergmann http://www.sebastian-bergmann.de/ GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

Andi Gutmans

21 years ago
In most cases method overloading is used for objects and not for classes (for example, initiating a SOAP object and then calling methods on it.). It doesn't make sense to mix these two things because it would lead to confusion what context the method was called in. You would either need another call back or pass a flag to __call() and in my opinion just doesn't seem to be worth it. Andi At 05:26 PM 11/7/2004 +0100, Timm Friebe wrote:

Jochem Maas

21 years ago
would it be doable (and more acceptable / less confusing) if __call could only be invoked statically if the class was abstract and vice versa only be invoked on objects if the class was not abstract? (the idea being to make the distinction during parsing rather than execution, allowing you to throw a parse error for incorrect usage [including use of $this in __call() when only allowing static calls]) Andi Gutmans wrote:

Marcus Börger

21 years ago
Hello Timm, you won't be able to tell from inside __call() whether a static or non static method was meant. The same holds for __get() and __set(). Also if we start using such code we'd need a class constructor. Thus this dicussion is leading to the following set of new magics: __static_get __static_set __static_call __static_construct regards marcus p.s.: something usefull when it comes to aspect oriented programming Sunday, November 7, 2004, 5:26:12 PM, you wrote:
> Hi, > is there any reason why __call shouldn't be invoked for static method > calls?
> Reproduce > --------- > php5 -r 'class A { function __call($name, $args) { var_dump($name, > $args); } } A::foo();'
> Actual result > ------------- > Fatal error: Call to undefined method A::foo() in Command line code on > line 1
> Expected result > --------------- > string(3) "foo" > array(0) { > }
> - Timm
-- Best regards, Marcus mailto:helly@php.net

Stanislav Malyshev

21 years ago
MB>> you won't be able to tell from inside __call() whether a static or MB>> non static method was meant. Technically, it's not a big problem IMO - there could be an argument added or some other solution, like presence of $this. MB>>non static method was meant. The same holds for __get() and __set(). MB>>Also if we start using such code we'd need a class constructor. Thus MB>>this dicussion is leading to the following set of new magics: MB>> MB>>__static_get MB>>__static_set MB>>__static_call MB>>__static_construct What do you mean by __static_construct? When do you expect it to be called? And, BTW - if you need to override method calls, etc. for a global object, why not to use singletons?
-- Stanislav Malyshev, Zend Products Engineer stas@zend.com http://www.zend.com/ +972-3-6139665 ext.115

Marcus Börger

21 years ago
Hello Stanislav, Monday, November 8, 2004, 11:29:13 AM, you wrote: MB>>> you won't be able to tell from inside __call() whether a static or MB>>> non static method was meant.
> Technically, it's not a big problem IMO - there could be an argument added > or some other solution, like presence of $this.
Adding an argument would be a major BC but sure is_null($this) would work, only it would be another big slowdown. MB>>>non static method was meant. The same holds for __get() and __set(). MB>>>Also if we start using such code we'd need a class constructor. Thus MB>>>this dicussion is leading to the following set of new magics: MB>>> MB>>>__static_get MB>>>__static_set MB>>>__static_call MB>>>__static_construct
> What do you mean by __static_construct? When do you expect it to be > called? And, BTW - if you need to override method calls, etc. for a > global object, why not to use singletons?
I didn't say it is necessary :-) __static_construct would be called the first time the class is going to be used. Best regards, Marcus mailto:helly@php.net

Stanislav Malyshev

21 years ago
MB>>Adding an argument would be a major BC but sure is_null($this) would work, MB>>only it would be another big slowdown. I don't think 2-3 additional opcodes are a "big" slowdown - if you are using non-default ctors and accessors anyway, you probably are doing something order of magnitude bigger there, not to mention PHP function call is costly by itself. As for BC - I think it can be made so it would accept old code too, and some set of rules could be made about when to call what - e.g., basing on number of arguments. If, of course, the whole thing is needed anyway :) MB>>__static_construct would be called the first time the class is going to be MB>>used. The idea doen't seem appealing to me... I wonder why one would need such tricks and why one won't use more civilized way of doing things - like appropriate patterns which don't have to require such magic.
-- Stanislav Malyshev, Zend Products Engineer stas@zend.com http://www.zend.com/ +972-3-6139665 ext.115

Timm Friebe

21 years ago
On Mon, 2004-11-08 at 11:18, Marcus Boerger wrote:
> Hello Timm, > > you won't be able to tell from inside __call() whether a static or > non static method was meant.
isset($this) does work fine.
> The same holds for __get() and __set(). > Also if we start using such code we'd need a class constructor.
Why?
> Thus this dicussion is leading to the following set of new magics:
[...] Instead of this: How about an extra (third) parameter $context to __call() which holds either object $this or string $classname. The signature would then be: mixed __call(string $name, array $args [, mixed $context]); Checking whether __call() was statically invoked could either be performed via code such as: is_object($context) ? 'in context of '.get_class($context) : 'statically in class '.$context On Mon, 2004-11-08 at 00:26, Andi Gutmans wrote:
> In most cases method overloading is used for objects and not for classes > (for example, initiating a SOAP object and then calling methods on it.). > It doesn't make sense to mix these two things because it would lead to > confusion what context the method was called in. You would either need > another call back or pass a flag to __call() and in my opinion just doesn't > seem to be worth it.
I think an extra flag wouldn't really hurt. No BC issue btw (mentioned in another mail), extra parameters are always ignored. Just like the set_error_handler() callback which you can add the array $context parameter to. - Timm