201

What is the difference between using self and static in the example below?

class Foo
{
    protected static $bar = 1234;

    public static function instance()
    {
        echo self::$bar;
        echo "\n";
        echo static::$bar;
    }

}

Foo::instance();

produces

1234
1234
yivi
  • 42,438
  • 18
  • 116
  • 138
cwd
  • 53,018
  • 53
  • 161
  • 198
  • 2
    @deceze: That's a similar question, but it isn't a duplicate. This one asks about using the keywords with properties, while that asks about using them with constructors. – BoltClock Jul 29 '12 at 14:55

5 Answers5

255

When you use self to refer to a class member, you're referring to the class within which you use the keyword. In this case, your Foo class defines a protected static property called $bar. When you use self in the Foo class to refer to the property, you're referencing the same class.

Therefore if you tried to use self::$bar elsewhere in your Foo class but you had a Bar class with a different value for the property, it would use Foo::$bar instead of Bar::$bar, which may not be what you intend:

class Foo
{
    protected static $bar = 1234;
}

class Bar extends Foo
{
    protected static $bar = 4321;
}

When you call a method via static, you're invoking a feature called late static bindings (introduced in PHP 5.3).

In the above scenario, using self will result in Foo::$bar(1234). And using static will result in Bar::$bar (4321) because with static, the interpreter takes into account the redeclaration within the Bar class during runtime.

// self
var_dump(Foo::$bar);
// (int) 1234

// static
var_dump(Bar::$bar);
// (int) 4321

You typically use late static bindings for methods or even the class itself, rather than properties, as you don't often redeclare properties in subclasses; an example of using the static keyword for invoking a late-bound constructor can be found in this related question: New self vs. new static

However, that doesn't preclude using static with properties as well.

Tomas Votruba
  • 23,240
  • 9
  • 79
  • 115
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • You might very easily redeclare in the child class, the parent class might be a default value that the child class uses unless they re-declare. If you are in the parent class, I guess it is safe to use self::, and if in a child class, you could come up with an argument to use either one, but self:: will also work if you dont expect to re-declare ever. – Andrew Feb 03 '17 at 16:37
  • 7
    go to [phpfiddle.org](http://phpfiddle.org/) and run this `a(); ?>` – Yevgeniy Afanasyev May 23 '19 at 01:31
  • 3
    The first two paragraph wording is confusing, has an ambiguous pronoun, "it", and is also redunant, as a later paragraphs explains the same information more clearly. I suggest replacing the first two paragraphs with the later paragraph that starts with "In the above scenario" to the top. That way the bottom line, cut-to-the-chase answer is at the top. It's clear and easy to follow. – ahnbizcad Nov 13 '19 at 20:06
  • Another way to think about this: `self::$abc`, when used inside `class Foo` is the same as saying `Foo::$abc`. It won't be affected by any re-declaration of `$abc` in a subclass. AFAIK, the only reason to use `self` is as a shorthand, to avoid using the class name `Foo`, which may be longer. [It also means you can change the classname without changing all those places - but that isn't much of a reason IMHO.] (PHP's choice of names is unfortunate, and seems backwards; "static" is the one that can change - which is opposite to the colloquial meaning of the natural-language word "static".) – ToolmakerSteve Feb 16 '20 at 05:36
50

I have small example showing difference between self and static. Using static:: performs Late Static Binding and thus it binds the variable value from child class.

class A { // Base Class
    protected static $name = 'ClassA';
    public static function getSelfName() {
        return self::$name;
    }
    public static function getStaticName() {
        return static::$name;
    }
}

class B extends A {
    protected static $name = 'ClassB';
}

echo A::getSelfName(); // ClassA
echo A::getStaticName(); // ClassA

echo B::getSelfName(); // ClassA
echo B::getStaticName(); // ClassB
Jsowa
  • 9,104
  • 5
  • 56
  • 60
31

With self call:

class Phone
{
    protected static $number = 123;
    
    public function getNumber()
    {
        return self::$number;
    }
}
class Fax extends Phone
{
    protected static $number = 234;
}

// Displays: "123"
echo (new Fax)->getNumber();

You can see above, even though we have overridden the $number with our Fax class, getNumber() still returns 123.

This because we have asked PHP to give us the variable where it was defined in -- which will return Phones variable instead.

If we swap the self call with static, we will get Faxs overridden value instead:

With static call:

class Phone
{
    protected static $number = 123;
    
    public function getNumber()
    {
        // return self::$number;

        return static::$number;
    }
}
class Fax extends Phone
{
    protected static $number = 234;
}

// Displays: "234"
echo (new Fax)->getNumber();
Steve Bauman
  • 8,165
  • 7
  • 40
  • 56
12

As mentioned one of the main differences is that static allows for late static bindings. One of the most useful scenarios that I found was for creating Base classes for Singleton Classes:

class A { // Base Class
    protected static $name = '';
    protected static function getName() {
        return static::$name;
    }
}
class B extends A {
    protected static $name = 'MyCustomNameB';
}
class C extends A {
    protected static $name = 'MyCustomNameC';
}

echo B::getName(); // MyCustomNameB
echo C::getName(); // MyCustomNameC

Using return static::$name in the Base class will return what was statically attached when it was extended. If you were to use return self::$name then B::getName() would return an empty string as that is what is declared in the Base class.

ggedde
  • 582
  • 5
  • 12
11

Maybe this self-explained code helps you:

class Foo 
{
    protected static $bar = 'parent value';
     
    public static function test() 
    {
         var_dump('I am your father');
         var_dump('self:: here means '.self::$bar);
         var_dump('static:: here means '.static::$bar);
    }
}
     
class Bar extends Foo 
{
     protected static $bar = 'child value';
     
     public static function test() 
     {
         parent::Test();
     
         var_dump('I am the child');
         var_dump('self:: here means '.self::$bar);
         var_dump('static:: here means '.static::$bar);
     }
}

Bar::test();
Foo::test();

This produces the following output (I have added Line Breaks for clarity):

'I am your father' (length=16)
'self:: here means parent value' (length=30)
'static:: here means child value' (length=31)

'I am the child' (length=14)
'self:: here means child value' (length=29)
'static:: here means child value' (length=31)

'I am your father' (length=16)
'self:: here means parent value' (length=30)
'static:: here means parent value' (length=32)
amir
  • 41
  • 7
dwoutsourcing
  • 127
  • 1
  • 6