What is the difference between self::$bar and static::$bar in PHP?

Viewed 86535

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
5 Answers

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

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();

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.

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)
Related