Declaring Static Methods in PHP

I was confused recently to realise that I had accidentally called a static method in PHP dynamically from another part of my code; I expected PHP to output warnings when this is done. On closer inspection I discovered that:

  • Static functions can be called dynamically
  • Dynamic functions generate an E_STRICT error if called statically

This made a lot more sense when I thought about it a bit more and wrote some toy code:

class MyClass                                                                                                                        
{                                                                                                                                    
    static function mystatic() {                                                                                                     
        echo "this was declared static!\n";                                                                                          
        return true;                                                                                                                 
    }                                                                                                                                
 
    function mydynamic() {                                                                                                           
        echo "a dynamic function said this\n";                                                                                       
        return true;                                                                                                                 
    }                                                                                                                                
}                                                                                                                                    
 
$obj = new MyClass();                                                                                                                
 
$obj->mydynamic();                                                                                                                   
MyClass::mydynamic();                                                                                                                
 
MyClass::mystatic();                                                                                                                 
$obj->mystatic();

When run with error_reporting set to E_ALL | E_STRICT, this outputs the following:


a dynamic function said this

Strict Standards: Non-static method MyClass::mydynamic() should not be called statically in /home/lorna/data/personal/publish/blog_stuff/static-functions.php on line 22
a dynamic function said this
this was declared static!
this was declared static!

Calling a Dynamic Method Statically

This generates the E_STRICT error, because a dynamic method expects to be in an object context, and with a static call this isn't the case. Methods to be called statically ought to be declared as such - it means we won't have access to $this, and using it in a static method generates an error to warn us that something is wrong. I think it makes much more sense to state whether the method is intended to be used statically or not - as much as an indicator to future programmers as anything else ("future programmers" includes me if I sleep between declaring the function and using it!)

Calling a Static Method Dynamically

This does not generate an error and for a while I thought this was a mistake, but actually it does make sense. A static method does not rely on the object context, it just takes inputs and generates outputs - and if it refers to static properties or other static methods then it does so in a way that is independent of how the method is called. So although there is probably something wrong if a static method is being called dynamically, it's unlikely to cause problems or be dangerous in the same way that calling a method intended for dynamic use in a static context could be.

I tripped myself up with this so I thought I would put it on my blog to remind me in the future which way round it is!

12 thoughts on “Declaring Static Methods in PHP

  1. Few people know, that PHP resolves $this to the the calling(!) object in static context.

    The mind-boggling problems this raises in some situations, were somewhat attenuated with the introduction of the concept of static methods in PHP5.

    But the underlying mechanism is unchanged even in PHP 5.3.3.

    Try the following example and scratch your head.

    [geshi lang=PHP]
    error_reporting(E_ERROR);

    class Playground extends PHPUnit_Framework_TestCase {
    public function testFoo() {
    $bar = new Bar();
    $this->assertSame('Bar', $bar->test());

    }
    }

    class Foo {
    public function test() {
    return get_class($this);
    }
    }

    class Bar {
    public function test() {
    return Foo::test();
    }
    }
    [/geshi]

  2. Of course there are ways to let Bar.test() return 'Bar' here.

    I wanted to point out, that PHP resolves $this as the caller(!) when a method is called statically.

    • Well actually your not calling it statically.

      In the same was parent::test() is not static, the way you called it is just choosing which parent to call.

  3. Foo::test() is a static call.

    In fact, parent::test() is a static call too. It works only, because PHP resolves $this as the caller, if a non static method is called statically.

  4. I think I can explain why you got confused with this and how you can understand it. The root of this confusing topic lies in the use of the "static" keyword, and we're carrying this confusion since C++ introduced its use as an indicator that a member of a class definition belongs to the class rather than to the objects of that class. I'm not sure why "static" was used, but probably it was done so to avoid adding a new keyword to the language ("static" actually means something different in C).

    Let's explain this in Layman's terms:

    Using "static" inside a class doesn't mean "static", it means "this belongs to the class, not to the objects"

    This use of "static" leads to further confusion, when you invoke a "static" method you aren't "statically calling a method", you're just calling a method in the scope of a class. This also applies to "non-static" methods, you aren't "dinamically calling a method", you're just calling a method in the scope of an object. The key point here is scope resolution, if you're already in the scope of an object you can do either $this->foo() or self::foo() and expect the exact same result.

    "Statically calling" and "dinamycally calling" actually mean something else. The key difference between a "static invocation" and a "dynamic invocation" is when the target of the invocation is resolved. In a static invocation the target is resolved during compilation, in a dynamic invocation the target is resolved in runtime.

    In Layman's terms:

    Static call means "we know for sure who will receive this call when the program is ran".

    Dynamic call mean "we'll find out who will receive this call when the program is ran"

    And please not that in a dynamic language such as php all invocations are dynamic.

  5. This would be truly useful for code reuse. I'd love to be able to do something like this that allows to set config settings across all objects, and individually by object:

    class Test
    {
    protected $_config = array();
    protected static $_staticConfig = array();

    public function __construct($config = array())
    {
    $this->setConfig($config);
    }

    public function setConfig($config)
    {
    $this->_config = array_merge(
    $this->_config,
    self::$_staticConfig,
    $config
    );
    }

    public static function setStaticConfig($config)
    {
    self::$_staticConfig = $config;
    }

    protected static function _getConfig($item)
    {
    if (isset($this)) {
    if (isset($this->_config[$item])) {
    return $this->_config[$item];
    }
    } else {
    if (isset(self::$_staticConfig[$item])) {
    return self::$_staticConfig[$item];
    }
    }
    }
    }

    But there seems to be no good way to detect how a static method is being called. This unfortunately reduces the usefulness of this language feature.

  6. U saved my 2 hours ;) i spend 2 hours and then came to ur blog....i would have spent 2 more hours looking for this static thing :) thanks

  7. Thanks for this post, it helps me understand when using static and dynamic functions to avoid those lines of errors in my website logs, this will speed a little my web pages when there is really no errors at all on your code , that save a little chars to be written on your log files :)

    Thank you again for this information about static methods in php.

  8. In Short we can access only static method like :

    MyClass::mystatic();
    $obj->mystatic();

    if we not declare mystatic() method as static and call it, then it generates error....

Leave a Reply

Please use [code] and [/code] around any source code you wish to share.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>