Hello,
I posted the same topic on the general mailing list, but it appears this can
be posted here, as it is open to feedbacks and is about PHP implementation
of static functions.
I'm wondering if the following behaviour is a bug or a feature. The case is
quite complex, so let me explain my point of view.
here is the source :
<?php
class MyTest {
public function myfunc() {
echo get_class($this);
}
}
class MySecondTest {
public function test() {
MyTest::myfunc();
}
}
$test = new MySecondTest();
$test->test(); //output: "MySecondTest"
?>
In this case, $this is MySecondTest, which is relevant as it is the last
object context. But to my mind, this code should not work like this.
Imagine you are the developer of function MyTest. You want your code to
interact with other classes and being bugproof. 'MyTest' class here seems
OK: $this is expected to be 'MyTest' because function myfunc() is expected
to be called in a non-static context.
Programmer of the second function created this bug and this unattended
behaviour.
Maybe this can be done :
1/ Forbid calling the function in static context (How can I test this ?
$this is not NULL
there !).
2/ (or/and) Raise an error if a non static function is called as a static
one (if E_STRICT
is set, strict warning is already raised).
3/ Create two functions with the same name, one static and the other one
not. Unfortunately, this can't be done (yet ?).
What do you think ? What's your point of view on this ? I want your
feedbacks before opening a bug ticket, as it is not strictly a "bug"...
Hello,
I posted the same topic on the general mailing list, but it appears this can
be posted here, as it is open to feedbacks and is about PHP implementation
of static functions.I'm wondering if the following behaviour is a bug or a feature. The case is
quite complex, so let me explain my point of view.
here is the source :<?php
class MyTest {
public function myfunc() {
echo get_class($this);
}
}
class MySecondTest {
public function test() {
MyTest::myfunc();
}
}$test = new MySecondTest();
$test->test(); //output: "MySecondTest"?>
In this case, $this is MySecondTest, which is relevant as it is the last
object context. But to my mind, this code should not work like this.Imagine you are the developer of function MyTest. You want your code to
interact with other classes and being bugproof. 'MyTest' class here seems
OK: $this is expected to be 'MyTest' because function myfunc() is expected
to be called in a non-static context.Programmer of the second function created this bug and this unattended
behaviour.Maybe this can be done :
1/ Forbid calling the function in static context (How can I test this ?
$this is notNULL
there !).
2/ (or/and) Raise an error if a non static function is called as a static
one (ifE_STRICT
is set, strict warning is already raised).
3/ Create two functions with the same name, one static and the other one
not. Unfortunately, this can't be done (yet ?).What do you think ? What's your point of view on this ? I want your
feedbacks before opening a bug ticket, as it is not strictly a "bug"...
Comments from a lurker...
For better or worse, it's been well documented that what you are
describing is php's behavior and it would be an enormous backwards
compatibility break to change it. Consider the following example, in
which two generally unrelated class heirarchies have enough in common
somewhere in the tree that some would be inclined to use multiple
inheritance:
<?php
class ABase {
public $a;
}
class A extends ABase {
public $x;
function f() {
HelpsAandB::f();
}
}
class BBase {
public $b;
}
class B extends BBase {
public $x;
function f() {
HelpsAandB::f();
}
}
class HelpsAandB {
function f() {
var_dump($this->x);
}
}
$example = new A;
$example->x = 5;
$example->f();
?>
Is that a messed up design? Almost certainly. Is it a nightmare to
re-design/re-implement many tens of thousands of lines of code that rely
on such behavior? Unfortunately, that's true also. (You may have
guessed that I'm responsible for such code and most of it was written
before I joined the company.)
I like to think this rules out options 1 and 2. I'm not sure about
option 3.
Maybe there could be a function that returns whether the current
function call is associated with the current object (ie whether it was
called via :: or ->). I'm not an internals expert.
Maybe to address backwards compatibility and address the concern you
raise, there could be a "nonstatic" keyword. php would throw an error
if a function declared "nonstatic" is called using ::.
- Todd
Hello,
I posted the same topic on the general mailing list, but it appears this
can
be posted here, as it is open to feedbacks and is about PHP implementation
of static functions.I'm wondering if the following behaviour is a bug or a feature. The case is
quite complex, so let me explain my point of view.
here is the source :<?php
class MyTest {
public function myfunc() {
echo get_class($this);
}
}
class MySecondTest {
public function test() {
MyTest::myfunc();
}
}$test = new MySecondTest();
$test->test(); //output: "MySecondTest"?>
not sure if this was mentioned on the general list but, i believe what youre
describing is documented in the manual under php5 classes/objects -> "the
basics":
http://www.php.net/manual/en/language.oop5.basic.php
$this is a reference to the calling object (usually the object to which the
method belongs, but can be another object, if the method is called
statically http://www.php.net/manual/en/language.oop5.static.php from the
context of a secondary object).
-nathan
Hi,
not sure if this was mentioned on the general list but, i believe what
youre describing is documented in the manual under php5 classes/objects ->
"the basics":http://www.php.net/manual/en/language.oop5.basic.php
$this is a reference to the calling object (usually the object to which
the method belongs, but can be another object, if the method is called
statically http://www.php.net/manual/en/language.oop5.static.php from
the context of a secondary object).-nathan
I know this behaviour is fully documented, but I was more concerned about
"is it a 'normal' behaviour ?". How can a programmer controls the class he
wrote, and make it absolutely bugproof ? How can he detect his function was
called in a static context and forbid it (or write specific code for) ?
Olivier
Hi,
not sure if this was mentioned on the general list but, i believe what
youre describing is documented in the manual under php5 classes/objects ->
"the basics":http://www.php.net/manual/en/language.oop5.basic.php
$this is a reference to the calling object (usually the object to which
the method belongs, but can be another object, if the method is called
statically http://www.php.net/manual/en/language.oop5.static.php from
the context of a secondary object).-nathan
I know this behaviour is fully documented, but I was more concerned about
"is it a 'normal' behaviour ?". How can a programmer controls the class he
wrote, and make it absolutely bugproof ? How can he detect his function was
called in a static context and forbid it (or write specific code for) ?
well, the access to $this of the secondary object is limited. so the only
way it really does anything useful is if member variables you wish to access
are marked as public; making it mostly useless imo.. but anyway all youd
need to do is mark member vars as protected or private. (personally, i think
it should be able to access protected vars, since the class which invokes
the other statically is essentially sanctioning access to its instance
variables).
<?php
class A {
public function showOtherClassInstanceVar($varname) {
var_dump($this->$varname);
}
}
class B {
public $a = 1;
protected $b = 2;
private $c = 3;
public function dumpViaMixin() {
A::showOtherClassInstanceVar('a');
A::showOtherClassInstanceVar('b');
A::showOtherClassInstanceVar('c');
}
}
$b = new B();
$b->dumpViaMixin();
outputs
int(1)
then the error log shows,
[11-Mar-2009 17:01:03] PHP Fatal error: Cannot access protected property
B::$b in /Users/nnobbe/testDelegation.php on line 5
[11-Mar-2009 17:01:03] PHP Stack trace:
[11-Mar-2009 17:01:03] PHP 1. {main}() /Users/nnobbe/testDelegation.php:0
[11-Mar-2009 17:01:03] PHP 2. B->dumpViaMixin()
/Users/nnobbe/testDelegation.php:22
[11-Mar-2009 17:01:03] PHP 3. A->showOtherClassInstanceVar()
/Users/nnobbe/testDelegation.php:16
so you should be able to protect your classes w/o too much trouble.
-nathan
Olivier Doucet wrote:
Hi,
not sure if this was mentioned on the general list but, i believe what
youre describing is documented in the manual under php5 classes/objects ->
"the basics":http://www.php.net/manual/en/language.oop5.basic.php
$this is a reference to the calling object (usually the object to which
the method belongs, but can be another object, if the method is called
statically http://www.php.net/manual/en/language.oop5.static.php from
the context of a secondary object).-nathan
I know this behaviour is fully documented, but I was more concerned about
"is it a 'normal' behaviour ?". How can a programmer controls the class he
Yes
wrote, and make it absolutely bugproof ? How can he detect his function was
called in a static context and forbid it (or write specific code for) ?
You can't unless you do some obtuse kind of:
if (isset($this) && $this instanceof MyClass)
But even this results in terrible and subtle mistakes if you happen to
call a "static" method from within a method of a subclass of MyClass.
instead use
static function blah()
for static functions, and $this simply will not be available.
Don't call non-static methods statically unless you want trouble.
"static" was introduced precisely for this reason.
Trying to make functions work as both dynamic and static is a disaster,
and we have had endless intractable problems with the most prevalent
implementation of this double design in the PEAR base class,
specifically with PEAR::raiseError(). Just don't do it.
Greg