Strange PHP scoping

Posted on Tuesday, May 11th, 2010 under , ,

I came to the conclusion that PHP is the programing language with the weirdest features. After the variable variables mess, that allows to you to name your variables stuff like !@#$%^&*()_+= and not be able to use them directly, I thought I saw everything. But no, yesterday I’ve bumped in another strange PHP feature. An even stranger feature.

Take a look at the code below:

class Example
{
    public function dynamicMethod($string)
    {
        // calls method baz() of the same class
        // class Example *does not have* a baz() method 
        $this->baz($string);
    }    
}
 
class Foo
{
    public function bar()
    {
        // a dynamic method called statically
        // no Example object is being instantiated
        Example::dynamicMethod('whatever');
    }
 
    public function baz($string)
    {
        echo 'Method baz() called with param "' . $string . '"' . PHP_EOL;
    }
}
 
$foo = new Foo();
$foo->bar();

What do you think the code will do? Yield an exception? A syntax error? Work? Well, strangely enough, it works:

Tudor-Barbus-MacBook% php blog-example.php
Method baz() called with param "whatever"

…and it seems that this feature is here to stay and be supported in the future, since I’m using the new PHP 5.3 version:

Tudor-Barbus-MacBook% php -v
PHP 5.3.1 (cli) (built: Feb 11 2010 02:32:22) 
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies

I wonder how this can be useful to somebody.

Related posts

14 Responses to “Strange PHP scoping”

Trackbacks (1)

Comments (13)

  1. Andy Roberts

    Interesting, is this an unexpected result of late static binding?

    But this example is not implemented in the context of static inheritance and late static binding resolution would stop at a fully resolved static call.

    Hmmm!

  2. Siderite

    Feels a little like javascript, when you execute a function in a different context via call/apply.

  3. Tudor

    @Andy Roberts Call me old fashioned, but if you call a method statically you shouldn’t have the $this pointer in its body. And it should be declared as “static” in the first place. Anyway, this is weird! I can’t imagine any scenario in which this would be useful.

    @Siderite Yes, it looks like a closure. But a weird closure that doesn’t bring anything useful….

  4. Ionut G. Stan

    You should enable stricts mode, so that you get a warning for calling a non-static method in a static context. I’m pretty sure this behaviour remained in the language because the internal devs are freaks about not breaking the API even between major versions.

  5. Mihai Brehar

    Maybe you should fill a bug report :)

  6. Tudor

    It’s too well supported to be a bug…

  7. Ionut G. Stan

    It’s not a bug, it’s just a remnant of the PHP 4 era when there was no explicit declaration for static methods. You simply called it statically and expect a runtime error if someone use $this inside that method.

  8. Tudor

    But it doesn’t throw a runtime error. It substitutes $this with the caller object. Weird…

    And PHP 4 died out like 4 years ago…let’s move on people :)

  9. scribu

    @Andy Roberts Call me old fashioned, but if you call a method statically you shouldn’t have the $this pointer in its body.

    As a counter example, think about parent::some_method(). You use the static resolution operator there too.

    Either way, really strange.

    What do you mean by “It’s too well supported to be a bug…” ?

  10. scribu

    BTW, you should style the blockquotes in your comments. ;-)

  11. Tudor

    @scribu I mean that this is obviously by design…

  12. gphilip

    Wow, this is weird, but I can imagine an excellent use, which is an implementation of multiple inheritance.

  13. Tudor

    Interesting, that might work…

Leave a Reply