1. Schizophrenic Methods

    Occasionally, it is useful for a developer to determine if a method is being called statically (not in an object context -- Class::method() ), or "not statically" (in an object context -- $object->method()).

    This is normally (but incorrectly) done by checking $this:

    [php] class Foo { function bar() { echo "bar() called: " . (isset($this) ? 'non-statically' : 'statically'); } } [/php]

    Why the "but incorrectly", you might ask?

    A few weeks ago, I started maintaining PEAR::Mail_Mime -- it had a lot of reported bugs, and nobody was really taking care of the package. (I'm going to release 1.3.0RC1 within the next couple weeks)

    Anyway, without getting too far off-topic, one of the bugs was "Fatal error: Using $this when not in object context."

    Basically, the code was checking for $this->mailMimeDecode, but when called statically, $this was unset.

    My fix was to check if $this was set, but once committed, Jan Schneider sent me mail telling me that my patch would not work if the method was called statically from within another object.

    This hadn't even occurred to me, so I did some testing (and eventually updated the manual).

    Here's the scenario:

    [php] class A { function foo() { if (isset($this)) { echo '$this is defined ('; echo get_class($this); echo ")\n"; } else { echo "\$this is not defined.\n"; } } } class B { function bar() { A::foo(); } } $a = new A(); $a->foo(); A::foo(); $b = new B(); $b->bar(); B::bar(); [/php]

    The output:

    [code] $this is defined (a) $this is not defined. $this is defined (b) $this is not defined. [/code]

    As you can see (if you have the human parser module installed (-: ), $this is defined, and is the calling object, even when a method is called statically (but from the context of another object).

    So (and here's my point), how does a developer determine if a given method is called statically? Here's what I came up with (and is in Mail_Mime - CVS):

    [php] $isStatic = !(isset($this) && get_class($this) == __CLASS__); [/php]

    It seems a little hackish to be using __CLASS__, but nothing else came to mind, and it works in every test I came up with.

    Side note: When I stuck this stuff in the manual, its place in the oop4 docs is pretty good, but in the oop5 docs, I don't like that it's in The Basics but I don't know where else to put it. So, if anyone has a good suggestion, let me know.