9

So I recently ran across a code segment like this:

private static function FOO() {
        static $c = null;
        if ($c == null) {
            $c = new ParentClass_InnerClass();
        }
        return $c;
    }

So what is up with this code? How is this different from:

private static $C;

//other methods and fields    

private static function FOO() {
    if(!$self::c) {
        $self::c = new ParentClass_InnerClass();
    }
    return $self::c;
}

Or are they even the same concept?

thatidiotguy
  • 8,701
  • 13
  • 60
  • 105

3 Answers3

8

They are, essentially, the same concept, though the scope is different:

class Foobar
{
    private static $c = null;
    public static function FOO()
    {
        if (self::$c === null)
        {
            self::$c = new stdClass;
        }
        return self::$c;
    }
    public static function checkC()
    {
        if (self::$c === null)
        {
            return false;
        }
        return self::$c;
    }
}

Foobar::checkC();//returns false, as $c is null
//function checkC has access to $c
$returned = Foobar::FOO();//returns object
if ($returned === Foobar::checkC())
{//will be true, both reference the same variable
    echo 'The same';
}

Whereas, if we were to change the code to:

class Foobar
{
    public static function FOO()
    {
        static $c = null;
        if ($c === null)
        {
            $c = new stdClass;
        }
        return $c;
    }
    public static function checkC()
    {
        if ($c === null)
        {
            return false;
        }
        return $c;
    }
}

We will get a notice when calling checkC: undefined variable. the static variable $c is only accessible from within the FOO scope. A private property is scoped within the entire class. That's it really.
But really, do yourself a favour: only use statics if you need them (they're shared between instances, too). And in PHP, it's very rare you'll actually need a static.

Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • Hi! I get the difference, but I have to ask how come it doesn't reset $c = null on every call to FOO()? Thanks in advance – sale108 Jul 14 '21 at 09:42
  • @sale108 Haven't used PHP in 5 years, but a variable in a function declared as `static` creates a `zval` in memory with whatever value you assign to it in the declaration/initialisation statement. Whatever happens to that `zval` next updated the same object in memory. Essentially, think of `static $c = null;` as something that is executed once, and then skipped in subsequent calls – Elias Van Ootegem Jul 15 '21 at 11:35
  • Thanks! That's enough for me to investigate on my own :) – sale108 Jul 15 '21 at 12:54
7

They're the same concept, except that in the first code block, the static variable is local to the function, and such a static variable could be used in any function, even outside the context of a class:

function test() {
    static $counter = 0;
    return $counter++;
}

echo test(); // 0
echo test(); // 1
BenMorel
  • 34,448
  • 50
  • 182
  • 322
  • How? Its a private function. You mean another public function could pass the variable out? – thatidiotguy Oct 24 '13 at 15:20
  • No, this kind of variable is local to the function and cannot be used outside of it. I mean that you could use a static variable in any function, even if it's not a class method. – BenMorel Oct 24 '13 at 15:30
  • I updated my answer with an example in a simple function, outside of a class. – BenMorel Oct 24 '13 at 15:31
1

In the top example you can access $c only from the local scope (FOO()) and in the bottom example you can access $c from the entire class, so not only form FOO().

Joren
  • 3,068
  • 25
  • 44
  • So its forcing the singleton pattern for a private variable, but since its forcing you to go through `FOO()` you are guaranteeing it is initialized? – thatidiotguy Oct 24 '13 at 15:20
  • @thatidiotguy: yes, but forcing a class to be initialized can be done using the Factory pattern, too, aswel as by _using a constructor, and the `new` keyword_ [Don't use singletons](http://stackoverflow.com/questions/19564416/run-parent-non-static-function-from-singleton-childs-instance-property/19564563#19564563) – Elias Van Ootegem Oct 24 '13 at 15:25