What is the difference between self::$bar and static::$bar in 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 takes into account the redeclaration within the Bar
class during runtime.
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.
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.
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