Static call detection

php.internals

Marcus Bointon

21 years ago
How can you find out definitively if a method of a PHP class has been called statically, in both PHP 4 and 5? I'm aware of the way that $this behaves - this is not that old FAQ, but it's at the root of the problem. I can't find a straight answer - even an "it's not possible" would be more helpful. Just to illustrate: Class a { function foo(){ print "foo"; } function spanner() { a::foo(); } } Class b { function bar() { print "bar"; } function foobar() { a::foo(); } function foobar2() { $a = new a; $a->foo(); } } $a = new a; $b = new b; $a->foo(); //dynamic $b->bar(); //dynamic a::foo(); //static, $this undefined b::bar(); //static, $this undefined $b->foobar(); //statically calls a::foo() $b->foobar2(); //Dynamically calls a::foo() $a->spanner(); //Static call from an instance of itself The problem is in detecting the last 3 call types correctly. You can't look at $this because it can't tell you anything useful about the call's context, unless it's undefined, in which case you know for sure that the call is static. Is_a() etc seem to be no use, as $this. It seems that there would be a place for an additional predefined variable like $me or something that does contain the current instance, if any, and avoids the transitive nature of $this. I've asked this a couple of times on the general list, plus several forums, and aside from the usual pointers to the $this faq, no solution has been suggested, so I'm asking here. This has been bugging me for ages, and I've been resorting to param counting to work around it for now - is there a better way? Marcus
-- Marcus Bointon Synchromedia Limited: Putting you in the picture marcus@synchromedia.co.uk | http://www.synchromedia.co.uk

Wez Furlong

21 years ago
If a method is static, you should only ever call it statically. Doing any other tricks is just plain wrong. If you still want to know the answer, ask the question on the correct list; what you've asked has nothing to do with hacking on the internals of PHP in C. --Wez. On Mon, 04 Oct 2004 13:01:56 +0100, Marcus Bointon <marcus@synchromedia.co.uk> wrote:

Christian Schneider

21 years ago
Wez Furlong wrote:
> If a method is static, you should only ever call it statically. > Doing any other tricks is just plain wrong.
I dare to disagree. For tool functions it often makes sense to make them statically callable while you still might want to use them in an object instance context respecting the instance's state. It may seem a bit hacky but I like PHP for being dynamic enough to allow this. Different people use different styles and I wouldn't say "Using exceptions is just plain wrong" even though I don't like them ;-)
> If you still want to know the answer, ask the question on the correct > list; what you've asked has nothing to do with hacking on the > internals of PHP in C.
He is asking for a mechanism to properly determine the static/non-static status of a call and I assume he also suggests to add such a mechanism in case it doesn't exist so I think your answer should be less hostile as it concerns internals IMHO. - Chris

Wez Furlong

21 years ago
I was asked off-list by someone else why I thought it was wrong, it turns out that I wasn't as clear as I could have been, so I'm going to follow up here and then withdraw (because I don't consider it an internals matter). It *is* ok to have a static method and call it either statically or not, provided that the method still behave statically (eg: the same) in both contexts. It is *not* ok to have a static method try and work like a non static method. In PHP 5, declaring a static method will prevent $this from being initialized. static means static. Take this as a hint that what you're trying to do it wrong :-) If you want to hack around the guts and do unsupported stuff like this, be prepared for your code to break in future versions of PHP. *cough* gallery assigning to $this *cough* --Wez. On Mon, 04 Oct 2004 14:34:36 +0200, Christian Schneider <cschneid@cschneid.com> wrote:

Hans Lellelid

21 years ago
Wez Furlong wrote:
> It is *not* ok to have a static method try and work like a non static method. > In PHP 5, declaring a static method will prevent $this from being initialized. > static means static. Take this as a hint that what you're trying to > do it wrong :-)
As others have mentioned on the list (and I know I've brought this up before too), it would be *extremely* useful to be able to do this. i.e. use the method statically for generic cases and allow instance objects to use a more specialized behavior. Why is it "wrong"? It feels intuitive to me, and seems like the kind of feature that would make people choose an interpreted language like PHP as opposed to Java, C#, etc. It'd be really cool, and [without thinking about it too much] I don't see the problem it creates. Certainly there's lots of PHP4 code that did that in a pretty hack, half-working way: if(isset($this)) {...}. Cheers, Hans

Marcus Bointon

21 years ago
on 4/10/04 13:34, Christian Schneider at cschneid@cschneid.com wrote:
> I dare to disagree. For tool functions it often makes sense to make them > statically callable while you still might want to use them in an object > instance context respecting the instance's state. It may seem a bit > hacky but I like PHP for being dynamic enough to allow this.
In this case I was writing a 'delete' method that would either delete the current object's database record, or if passed an ID and called statically (hence the need to detect it), the record corresponding to that id.
> He is asking for a mechanism to properly determine the static/non-static > status of a call and I assume he also suggests to add such a mechanism > in case it doesn't exist so I think your answer should be less hostile > as it concerns internals IMHO.
I asked on internals because although this appears as a user-level problem, knowing the definitive answer requires knowledge of PHP internals. on 4/10/04 14:09, Wez Furlong at kingwez@gmail.com wrote:
> It is *not* ok to have a static method try and work like a non static method. > In PHP 5, declaring a static method will prevent $this from being initialized. > static means static. Take this as a hint that what you're trying to > do it wrong :-)
If $this is always cleared in a static method, there really is no way of telling of the call was originally made statically or not (even introspection can only tell you how it's supposed to be, not how it actually happened). Anyway, I guess this is academic in PHP5, but it's still a concern in PHP4.
> If you want to hack around the guts and do unsupported stuff like > this, be prepared for your code to break in future versions of PHP. > *cough* gallery assigning to $this *cough*
I ran into that one back in early dev releases of PHP5 and improved my habits accordingly! To summarise, you can't tell, and you shouldn't be trying to anyway. Marcus
-- Marcus Bointon Synchromedia Limited: Putting you in the picture marcus@synchromedia.co.uk | http://www.synchromedia.co.uk

Christian Schneider

21 years ago
Marcus Bointon wrote:
> To summarise, you can't tell, and you shouldn't be trying to anyway.
That seems to be the consensus. I find it a pity as I like PHP for giving programmers freedom instead of telling them how to do things but oh well... :-) Over and out, - Chris

Marek Kilimajer

21 years ago
Marcus Bointon wrote:
> on 4/10/04 13:34, Christian Schneider at cschneid@cschneid.com wrote: > > >>I dare to disagree. For tool functions it often makes sense to make them >>statically callable while you still might want to use them in an object >>instance context respecting the instance's state. It may seem a bit >>hacky but I like PHP for being dynamic enough to allow this. > > > In this case I was writing a 'delete' method that would either delete the > current object's database record, or if passed an ID and called statically > (hence the need to detect it), the record corresponding to that id.
What about: class A { function delete($id = null) { if(is_null($id)) { $id = $this->id; } } }