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

PhpOopPhp 5.3

Php Problem Overview


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

Php Solutions


Solution 1 - Php

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: https://stackoverflow.com/questions/5197300/new-self-vs-new-static

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

Solution 2 - Php

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 B::getSelfName(); // ClassA
echo B::getStaticName(); // ClassB

Solution 3 - Php

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 static::$number;
    }
}
class Fax extends Phone
{
    protected static $number = 234;
}

// Displays: "234"
echo (new Fax)->getVar();

Solution 4 - Php

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.

Solution 5 - Php

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)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncwdView Question on Stackoverflow
Solution 1 - PhpBoltClockView Answer on Stackoverflow
Solution 2 - PhpJsowaView Answer on Stackoverflow
Solution 3 - PhpSteve BaumanView Answer on Stackoverflow
Solution 4 - PhpggeddeView Answer on Stackoverflow
Solution 5 - PhpdwoutsourcingView Answer on Stackoverflow