Static weirdness..

php.internals

John Coggeshall

22 years ago
http://bugs.php.net/bug.php?id=27304 Marcus says he's brought this up before, and i think it really needs to be addressed before PHP 5 so I'm bringing it up again. I am told that currently we are allowing static methods to be called from an object context because of a performance hit if we check every call, but currently because $this is undefined regardless of context there is no way even for the developer to check if the method was called properly. John
-- -=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=- John Coggeshall http://www.coggeshall.org/ The PHP Developer's Handbook http://www.php-handbook.com/ -=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=-

Pierre-Alain Joye

22 years ago
On Wed, 18 Feb 2004 02:53:50 -0500 john@coggeshall.org (John Coggeshall) wrote:
> http://bugs.php.net/bug.php?id=27304 > > Marcus says he's brought this up before, and i think it really needs > to be addressed before PHP 5 so I'm bringing it up again. I am told > that currently we are allowing static methods to be called from an > object context because of a performance hit if we check every call, > but currently because $this is undefined regardless of context there > is no way even for the developer to check if the method was called > properly.
imho, this is the expected behavior. At least a notice should be raised. I do not see a reason to define $this if a method is explicitly defined as static (means it should not be called dynamically). Declare the same funciton as public|private|protected and everything works fine. pierre

John Coggeshall

22 years ago
> imho, this is the expected behavior. At least a notice should be raised. > I do not see a reason to define $this if a method is explicitly defined > as static (means it should not be called dynamically). Declare the > same funciton as public|private|protected and everything works fine.
There is no reason I can possibly imagine why methods declared as static should be allowed to be called from a non-static context. Sure, in my own classes I know not to call a method I declared as static from an instance. But IMO the whole point of static is to create a restriction in then engine keeping from anyone calling that function in anything other than a static context. class foo { static function bar() { echo "Hello.\n"; } function foobar(); } $a = new foo; $b->bar(); This is a completely acceptable thing, and it is IMO completely wrong to even allow in the engine. foo::bar() should be the only accepted syntax for static functions. If I download a new class from some site, or otherwise use someone else's code, how do I know other than digging through the source on a method's context? If $this isn't set I can't do the check, and if then engine doesn't do it there isn't a way to tell the difference.
-- -=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=- John Coggeshall http://www.coggeshall.org/ The PHP Developer's Handbook http://www.php-handbook.com/ -=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=-

George Schlossnagle

22 years ago
On Feb 18, 2004, at 12:14 PM, John Coggeshall wrote:
> This is a completely acceptable thing, and it is IMO completely wrong > to > even allow in the engine. foo::bar() should be the only accepted syntax > for static functions.
Maybe I'm having a slow-English day, but how is the first sentence here is not intrinsically self-contradictory? George

John Coggeshall

22 years ago
On Wed, 2004-02-18 at 12:21, George Schlossnagle wrote:
> Maybe I'm having a slow-English day, but how is the first sentence here > is not intrinsically self-contradictory?
:) class foo { static function bar() { } } $a = new foo(); $a->bar(); /* Unacceptable and contradictory to the concept of static */ foo::bar(); /* Acceptable */ John
-- -=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=- John Coggeshall http://www.coggeshall.org/ The PHP Developer's Handbook http://www.php-handbook.com/ -=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=-

Pierre-Alain Joye

22 years ago
On Wed, 18 Feb 2004 12:23:04 -0500 John Coggeshall <john@coggeshall.org> wrote:
> class foo { > static function bar() { > } > } > $a = new foo(); > $a->bar(); /* Unacceptable and contradictory to the concept of static > */ foo::bar(); /* Acceptable */
I have the same problem as George :) I did not understand well your original post. We are talking about the same thing. A notice (error sounds too drastic here) should be raised if a static method is called from the instanciated object. pierre

John Coggeshall

22 years ago
On Wed, 2004-02-18 at 12:30, Pierre-Alain Joye wrote:
> We are talking about the same thing. A notice (error sounds too > drastic here) should be raised if a static method is called from the > instanciated object.
No. There is *no* reason why static methods should be called from an object context. Doing so is more than a notice -- its flat out wrong and defeats the entire purpose of having static in the first place... John
-- -=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=- John Coggeshall http://www.coggeshall.org/ The PHP Developer's Handbook http://www.php-handbook.com/ -=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=-

Pierre-Alain Joye

22 years ago
On Wed, 18 Feb 2004 12:33:35 -0500 John Coggeshall <john@coggeshall.org> wrote:
> No. There is *no* reason why static methods should be called from an > object context. Doing so is more than a notice -- its flat out wrong > and defeats the entire purpose of having static in the first place...
I only say that a error (fatal or no) may be not the good choice. But I do not care that much as far as there is at least a notice :) pierre

Wez Furlong

22 years ago
C++ allows $a->bar() when bar() is a static method (yes, it is called in a static context there too). IMO, there should be no error, warning or notice here. --Wez.

Cristiano Duarte

22 years ago
On Wed, 18 Feb 2004 17:37:31 +0000, Wez Furlong wrote:
> C++ allows $a->bar() when bar() is a static method (yes, it is called > in a static context there too). > > IMO, there should be no error, warning or notice here. >
I Agree. PHP is fine the way it is. Cristiano Duarte

Unnamed Person

22 years ago
Well, calling a static method from an instance breaks down the logic. If it is static, then the instance has absolutely no bearing when calling it. Therefore, it logically makes sense to call only from the class name. Moreover, making a distinction between the method calling syntax begins to make the distinction between class objects and instance objects. I have a class which deals directly with classes and their static methods as if they are objects. This is a powerful notion that still needs more support in the Zend engine. The call for static method should be: ClassName->method(); Herr Witten

Unnamed Person

22 years ago
On Friday 20 February 2004 20:23, Herr Witten wrote:
> Well, calling a static method from an instance breaks down the logic. > If it is static, then the instance has absolutely no bearing when > calling it. Therefore, it logically makes sense to call only from the > class name. > > Moreover, making a distinction between the method calling syntax begins > to make the distinction between class objects and instance objects. I > have a class which deals directly with classes and their static methods > as if they are objects. This is a powerful notion that still needs more > support in the Zend engine. > > The call for static method should be: > > ClassName->method(); > > Herr Witten > > > C++ allows $a->bar() when bar() is a static method (yes, it is called > > in a static context there too). > > > > IMO, there should be no error, warning or notice here.
Regardless of the final implementation, I think access to static methods and static class variables should be consistent. Currently, you cannot access a class variable via an object instance. And for what it's worth, I see no reason why static methods cannot be called from objects. Follow Java/C++ in this case.

Hans Lellelid

22 years ago
Hi - Pierre-Alain Joye wrote:
> On Wed, 18 Feb 2004 12:23:04 -0500 > John Coggeshall <john@coggeshall.org> wrote: > >>class foo { >> static function bar() { >> } >>} >>$a = new foo(); >>$a->bar(); /* Unacceptable and contradictory to the concept of static >>*/ foo::bar(); /* Acceptable */ > > > I have the same problem as George :) I did not understand well your > original post. > > We are talking about the same thing. A notice (error sounds too > drastic here) should be raised if a static method is called from the > instanciated object. >
I disagree w/ any sort of error being raised by calling a static method from object context. I think it should be allowed because 1) there is already the stuff in static to disallow any reference to $this, so there is no danger of a static method messing w/ instance variables. (i.e. if you're calling it by accident, you'll probably find out pretty quickly) 2) In some cases it is useful to instantiate an otherwise static class for the sake of passing it to some code that doesn't know the name of the static class. For example in Propel (PHP5 Torque port) the "Peer" classes are static classes that do work on entities -- like inserting them in the database, etc. If I have an array of Entity objects, I might want to get access to the Peer class that handles those entities, so I have: foreach($entities as $ent) { $peer = $ent->getPeer(); // e.g. might be BookPeer $peer->doSelect(new Criteria()); //static: BookPeer::doSelect() } This [taken from Java Torque impl] is particularly useful because the alternative is having to invoke the method using call_user_func() or eval() (yuk!). Hans

Timm Friebe

22 years ago
On Wed, 2004-02-18 at 18:40, Hans Lellelid wrote:
> Hi -
[...]
> foreach($entities as $ent) { > $peer = $ent->getPeer(); // e.g. might be BookPeer > $peer->doSelect(new Criteria()); //static: BookPeer::doSelect() > }
$m= new Reflection_Method($ent->getPeer(), 'doSelect'); $m->invoke(NULL, new Criteria()); /* untested */ - Timm

Hans Lellelid

22 years ago
Timm Friebe wrote:
> On Wed, 2004-02-18 at 18:40, Hans Lellelid wrote: > >>foreach($entities as $ent) { >> $peer = $ent->getPeer(); // e.g. might be BookPeer >> $peer->doSelect(new Criteria()); //static: BookPeer::doSelect() >>} > > > $m= new Reflection_Method($ent->getPeer(), 'doSelect'); > $m->invoke(NULL, new Criteria()); > > /* untested */ >
Yeah, I'm sure there's a way to get something like that to work also. I'm not sure that's prefereable to call_user_func(), honestly -- and it doesn't get around the basic problem which is that calling code needs to know whether methods are static. I guess I'm not sure why this is necessary ... As Hartmut & Lukas mention, I don't know why the class consumer *needs* to know that it's static. Clearly internally there should be no possibility of referencing $this. Also in my example the entire class is static -- i.e. all methods are static -- but what about cases where one or two methods in a class are static. Now $a->methodName() will work for most but all of a sudden you have to do $a::staticMethodName() for the static members. What I see as the workaround is creating static methods that aren't marked as static -- e.g. that would address the issue in my example above. I think that's a lot worse than allowing invocation of static methods using instances, however, because I do want developers who read the API docs to know these are static functions. Hans

Marcus Börger

22 years ago
Hello Hans, Thursday, February 19, 2004, 4:14:53 PM, you wrote:
> Timm Friebe wrote: >> On Wed, 2004-02-18 at 18:40, Hans Lellelid wrote: >> >>>foreach($entities as $ent) { >>> $peer = $ent->getPeer(); // e.g. might be BookPeer >>> $peer->doSelect(new Criteria()); //static: BookPeer::doSelect() >>>} >> >> >> $m= new Reflection_Method($ent->getPeer(), 'doSelect'); >> $m->invoke(NULL, new Criteria()); >> >> /* untested */ >>
> Yeah, I'm sure there's a way to get something like that to work also. > I'm not sure that's prefereable to call_user_func(), honestly -- and it > doesn't get around the basic problem which is that calling code needs to > know whether methods are static.
> I guess I'm not sure why this is necessary ...
> As Hartmut & Lukas mention, I don't know why the class consumer *needs* > to know that it's static. Clearly internally there should be no > possibility of referencing $this.
> Also in my example the entire class is static -- i.e. all methods are > static -- but what about cases where one or two methods in a class are > static. Now $a->methodName() will work for most but all of a sudden you > have to do $a::staticMethodName() for the static members.
> What I see as the workaround is creating static methods that aren't > marked as static -- e.g. that would address the issue in my example > above. I think that's a lot worse than allowing invocation of static > methods using instances, however, because I do want developers who read > the API docs to know these are static functions.
I hope nobody wants such strange things. Calling a static method from an instance is just one of the ways to get to the class of that method.
-- Best regards, Marcus mailto:helly@php.net

Ferdinand Beyer

22 years ago
On 18 Feb 2004 at 12:33, John Coggeshall wrote:
> No. There is *no* reason why static methods should be called from
an
> object context. Doing so is more than a notice -- its flat out wrong
and
> defeats the entire purpose of having static in the first place...
I agree with John. I would even go one step further and trigger a "call to undefined function" error. I would strictly separate the class scope from the instance scope, allowing both a static method and a normal method with the same name: class Example { static function dump() { print "This is the Example class.\n"; } function dump() { print "This is an Example object:\n"; var_dump($this); } } But I could live without that since it would certainly be very much work to implement such a change...
-- Ferdinand Beyer <fb@fbeyer.com>

Zeev Suraski

22 years ago
At 19:37 18/02/2004, Wez Furlong wrote:
>C++ allows $a->bar() when bar() is a static method (yes, it is called >in a static context there too). > >IMO, there should be no error, warning or notice here.
Same here. Zeev

Pierre-Alain Joye

22 years ago
On Wed, 18 Feb 2004 12:14:04 -0500 John Coggeshall <john@coggeshall.org> wrote:
> if I download a new class from some site, or otherwise use someone > else's code, how do I know other than digging through the source on > a method's context? If $this isn't set I can't do the check, and if > then engine doesn't do it there isn't a way to tell the difference.
To help John to do not read the sources ;-) (and many of us as well) it should be nice if the reflection api returns this infos in getMethods() result. For now only the methods name and the class name are returned. If it's possible. pierre

Greg Beaver

22 years ago
Hi, I agree that allowing $a->bar() with a static method is too confusing, and should not be allowed. However, the ability to call a static method of an object (variable class name, in other words), is invaluable. What if PHP simply allowed $object::staticMethod() syntax? I did some playing around, and although I wouldn't know how to disable $a->staticMethod(), this patch enables $a::staticMethod(). It also has another side effect <?php class foo { static function bar() { echo 'hello'; } } $bar = 'hello'; $a = new foo; $a->bar(); // this could be disabled to error out easily $a::bar(); // my patch now allows this to print "hello" $a::$bar(); // this also works $a::{'bar'}(); // even this works ?> If someone could get the patch to work with a T_STRING instead of an object_property, then it would disable the $a::$bar() and $a::{expression}() syntax. This is my first attempt at a patch of the core, please be gentle if it sucks. :) Thanks, Greg John Coggeshall wrote:

Hartmut Holzgraefe

22 years ago
Greg Beaver wrote:
> Hi, > > I agree that allowing $a->bar() with a static method is too confusing, > and should not be allowed. However, the ability to call a static method > of an object (variable class name, in other words), is invaluable. What > if PHP simply allowed $object::staticMethod() syntax?
Why do i (as a user of a class) have to know whether a member function is static or not? Having two different calling conventions is what appears to be confusing to me ...
-- Hartmut Holzgraefe <hartmut@php.net>

Lukas Smith

22 years ago
Hartmut Holzgraefe wrote:
> Greg Beaver wrote: > >> Hi, >> >> I agree that allowing $a->bar() with a static method is too confusing, >> and should not be allowed. However, the ability to call a static >> method of an object (variable class name, in other words), is >> invaluable. What if PHP simply allowed $object::staticMethod() syntax? > > > Why do i (as a user of a class) have to know whether a member function > is static or not? Having two different calling conventions is what > appears to be confusing to me ...
I agree with Hartmut. regards, Lukas Smith smith@backendmedia.com _______________________________ BackendMedia www.backendmedia.com berlin@backendmedia.com Linn Zwoch Smith GbR Pariser Str. 44 D-10707 Berlin Tel +49 30 83 22 50 00 Fax +49 30 83 22 50 07

Marcus Börger

22 years ago
Hello Hartmut, Thursday, February 19, 2004, 10:03:33 AM, you wrote:
> Greg Beaver wrote: >> Hi, >> >> I agree that allowing $a->bar() with a static method is too confusing, >> and should not be allowed. However, the ability to call a static method >> of an object (variable class name, in other words), is invaluable. What >> if PHP simply allowed $object::staticMethod() syntax?
> Why do i (as a user of a class) have to know whether a member function > is static or not? Having two different calling conventions is what > appears to be confusing to me ...
A static and a non static member function are two absolute completley different things. Anyway calling a static method from an instance as $instance->staticmethod() or $instance::staticmethod() should be allowed. I guess the latter is what Lukas and Hartmut meant.
-- Best regards, Marcus mailto:helly@php.net

Pierre-Alain Joye

22 years ago
On Thu, 19 Feb 2004 15:49:42 +0100 Marcus Boerger <helly@php.net> wrote:
> A static and a non static member function are two absolute completley > different things. Anyway calling a static method from an instance as > $instance->staticmethod() or $instance::staticmethod() should be > allowed. I guess the latter is what Lukas and Hartmut meant.
I discussed with Lukas what he meant by "I agree". A lot of misunderstanding in this thread :) One sure thing, $this should not be set in static methods. I do not care that much but I like to see a notice in E_STRICT mode if a method explicitly declared as static is called from an instance of the object. About this topic, see my other post. It's a patch that add fn_flags (method flags like public, private) to the getMethod() result. pierre

Derick Rethans

22 years ago
On Thu, 19 Feb 2004, Pierre-Alain Joye wrote:
> On Thu, 19 Feb 2004 15:49:42 +0100 > Marcus Boerger <helly@php.net> wrote: > > > A static and a non static member function are two absolute completley > > different things. Anyway calling a static method from an instance as > > $instance->staticmethod() or $instance::staticmethod() should be > > allowed. I guess the latter is what Lukas and Hartmut meant. > > I discussed with Lukas what he meant by "I agree". A lot of > misunderstanding in this thread :) > > One sure thing, $this should not be set in static methods.
But it should get set in non-static methods...which doesn't happen now :) Derick

Pierre-Alain Joye

22 years ago
On Thu, 19 Feb 2004 16:02:10 +0100 (CET) Derick Rethans <derick@php.net> wrote:
> But it should get set in non-static methods...which doesn't happen now > :)
$this is set in non static methods if the method is called from an instance of the object and not set if called statically. It's exactly the same behavior as php4. That's why I like the notice on a non static call of a static method, cleaner and no BC as the static methods did not exist in php4. See the tests script in the beginning of this thread. hth pierre

Marcus Börger

22 years ago
Hello Pierre-Alain, Thursday, February 19, 2004, 4:10:09 PM, you wrote:
> On Thu, 19 Feb 2004 16:02:10 +0100 (CET) > Derick Rethans <derick@php.net> wrote:
>> But it should get set in non-static methods...which doesn't happen now >> :)
> $this is set in non static methods if the method is called from an > instance of the object and not set if called statically. It's exactly > the same behavior as php4. That's why I like the notice on a non static > call of a static method, cleaner and no BC as the static methods did not > exist in php4.
But why the hell do you want a message, calling a static method from anywhere is absolutley fine. This of course includes calling a static method of an instance's class, however that is syntactically accomplished. I heared pear already mentioned in this thread. That cannot be of any reason with the ongoing effort to make statics work. First as i heared most of pear doesn't run on php5 and second pear of today uses php4 which didn't support statics and lots of other oo goodies. So it clear that pear has some bc problems when moving to version where all the workarounds are now solved by syntax. Best regards, Marcus mailto:helly@php.net

Pierre-Alain Joye

22 years ago
On Thu, 19 Feb 2004 16:21:50 +0100 Marcus Boerger <helly@php.net> wrote:
> But why the hell do you want a message, calling a static method from > anywhere is absolutley fine. This of course includes calling a static > method of an instance's class, however that is syntactically > accomplished.
I think it's cleaner, but as said, I do not care. There is no chance to get a compromise on that as it is the case in most OO topic here, too much OO pov and fanatics ;-)) However I like to get the flags from getMethods :)
> I heared pear already mentioned in this thread. That cannot be of any > reason with the ongoing effort to make statics work. First as i heared > most of pear doesn't run on php5 and second pear of today uses php4 > which didn't support statics and lots of other oo goodies. So it clear > that pear has some bc problems when moving to version where all the > workarounds are now solved by syntax.
There is no problem. PEAR runs with PHP5 (I use only php5 these days) And PEAR does not lead PHP devs but the counter, imho. pierre

Hartmut Holzgraefe

22 years ago
Pierre-Alain Joye wrote:
> And PEAR does not lead PHP devs but the counter, imho.
it_sure_doesnt (althoughItWouldLikeTo) ;)
-- Hartmut Holzgraefe <hartmut@php.net>

Marcus Börger

22 years ago
Hello Pierre-Alain, Thursday, February 19, 2004, 4:28:50 PM, you wrote:
> On Thu, 19 Feb 2004 16:21:50 +0100 > Marcus Boerger <helly@php.net> wrote:
>> But why the hell do you want a message, calling a static method from >> anywhere is absolutley fine. This of course includes calling a static >> method of an instance's class, however that is syntactically >> accomplished.
> I think it's cleaner, but as said, I do not care. There is no chance to > get a compromise on that as it is the case in most OO topic here, too > much OO pov and fanatics ;-))
> However I like to get the flags from getMethods :)
As mentioned beside you patch: php -r '$m = new reflection_method("reflection_method","export"); var_dump($m->isStatic());'
>> I heared pear already mentioned in this thread. That cannot be of any >> reason with the ongoing effort to make statics work. First as i heared >> most of pear doesn't run on php5 and second pear of today uses php4 >> which didn't support statics and lots of other oo goodies. So it clear >> that pear has some bc problems when moving to version where all the >> workarounds are now solved by syntax.
> There is no problem. PEAR runs with PHP5 (I use only php5 these days) > And PEAR does not lead PHP devs but the counter, imho.
Oh - great news to hear!
-- Best regards, Marcus mailto:helly@php.net

Zeev Suraski

22 years ago
At 17:21 19/02/2004, Marcus Boerger wrote:
>calling a static method from >anywhere is absolutley fine. This of course includes calling a static >method of an instance's class, however that is syntactically accomplished.
That's exactly correct. Zeev

Hartmut Holzgraefe

22 years ago
Pierre-Alain Joye wrote:
> One sure thing, $this should not be set in static methods.
ACK
-- Hartmut Holzgraefe <hartmut@php.net>

Greg Beaver

22 years ago
Pierre-Alain Joye wrote:
>One sure thing, $this should not be set in static methods. >
I completely agree - the headache of fixing PEAR's "kind of static" methods is really annoying, and not really fixable. A method should either be static, non-static, or split into two methods, one that is static, and one that is not. Language-level enforcement of not allowing $this in static methods is very nice. Grge

Hartmut Holzgraefe

22 years ago
Marcus Boerger wrote:
> A static and a non static member function are two absolute completley > different things.
sure they are (in certain ways), but when *calling* them (from a class users point of view, not an implementors point of view) the only difference is that the static member is guaranteed to not change the state of an instance while a non-static member is not besides that there is no difference for a caller/user of an instance and forcing him to know which member functions are static and which aren't just adds a level of inconvenience without gain so IMHO $instance->static() has to work classname::static() obviously has to work, too $instance::static() is optional
-- Hartmut Holzgraefe <hartmut@php.net>

Stephane Drouard

22 years ago
== Quote from Greg Beaver (greg@chiaraquartet.net)'s article
> <?php > class foo { > static function bar() > { > echo 'hello'; > } > } > > $bar = 'hello'; > $a = new foo; > $a->bar(); // this could be disabled to error out easily > $a::bar(); // my patch now allows this to print "hello" > $a::$bar(); // this also works > $a::{'bar'}(); // even this works > ?>
The idea is good, but the syntax "$a::bar()" seems to me that $a is the name of the class, not an instance. I would prefer that PHP supports: $class = get_class($a); $class::bar(); or, to make it shorter: get_class($a)::bar(); Anyway, if you need to call a class method, but you only know an instance of it, this is certainly because the class was not properly defined. A class method is a method that applies to the class, not instances. And a method that does not need to use $this is not necessarily a class method. Stephane

Andi Gutmans

22 years ago
This isn't a bug. The whole idea of a true static method is for $this not to be defined. Andi At 02:53 18/02/2004 -0500, John Coggeshall wrote: