What is the difference between self::$bar and static::$bar in PHP?
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
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.
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
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, it still returns 123
, because we have explicitly asked PHP for the self
variable, which in turn asks for Phone
s variable instead.
Now if we swap the self
call with static
, we will instead get Fax
s overridden value:
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();
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.