What is the difference between static::
and self::
in a PHP object oriented reference?
The simple answer is that most of the time, they are the same. There is a small difference between the two that many PHP developers and programmers do not know.
static::
, which was introduced in PHP 5.3, uses “late static bindings”. In other words, the most recent one. This is important when dealing with inheritance and overriding methods and members.
You can read about Late Static Bindings in the PHP manual.
self::
on the other hand references the class that it is in.
Here is some sample code that illustrates this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?php class Foo { protected static $x = 1234; public static function valueFoo() { echo self::$x . PHP_EOL . static::$x; } } class Bar extends Foo { protected static $x = 9876; } class Baz extends Bar { protected static $x = 4321; } Baz::valueFoo(); |
This code will have the following output:
1 2 |
1234 4321 |
In this example, class Baz
extends class Bar
, which extends class Foo
. Calling Baz::valueFoo()
, which is not overridden in either class Baz
nor Bar
, is executed in class Foo
.
self::$x
prints out the value of 1234
. Remember self::$x
references the class that the code is written in; in this case, Foo
.
static::$x
prints 4321
, as that was the latest override to $x
found in class Baz
.
The value of $x
from class Bar
is missing from the print out, as it is not the first nor the last.
I hope that is clear! Now lets muddy the waters a little.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<?php class Foo { protected static $x = 1234; public static function valueFoo() { echo self::$x . PHP_EOL . static::$x . PHP_EOL . "-----" . PHP_EOL; } } class Bar extends Foo { protected static $x = 9876; public static function valueBar() { echo self::$x . PHP_EOL . static::$x . PHP_EOL . parent::$x . PHP_EOL . "-----" . PHP_EOL; } } class Baz extends Bar { protected static $x = 4321; public static function valueBaz() { echo self::$x . PHP_EOL . static::$x . PHP_EOL . parent::$x . PHP_EOL . "-----" . PHP_EOL; } } Foo::valueFoo(); Bar::valueFoo(); Baz::valueFoo(); Bar::valueBar(); Baz::valueBar(); Baz::valueBaz(); |
The output is this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
1234 1234 ----- 1234 9876 ----- 1234 4321 ----- 9876 9876 1234 ----- 9876 4321 1234 ----- 4321 4321 9876 ----- |
Perfectly clear, right? It might not be. So here it is with some annotations:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
Foo::valueFoo(); 1234 self::$x, resolves to Foo:$x 1234 static::$x, resolves to Foo:$x ----- Bar::valueFoo(); 1234 self::$x, resolves to Foo:$x 9876 static::$x, resolves to Bar:$x ----- Baz::valueFoo(); 1234 self::$x, resolves to Foo:$x 4321 static::$x, resolves to Baz:$x ----- Bar::valueBar(); 9876 self::$x, resolves to Bar:$x 9876 static::$x, resolves to Bar:$x 1234 parent::$x, resolves to Foo:$x ----- Baz::valueBar(); 9876 self::$x, resolves to Bar:$x 4321 static::$x, resolves to Baz:$x 1234 parent::$x, resolves to Foo:$x ----- Baz::valueBaz(); 4321 self::$x, resolves to Baz:$x 4321 static::$x, resolves to Baz:$x 9876 parent::$x, resolves to Bar:$x ----- |
self::
resolves to the class that the self::
keyword is in.
static::
resolves to the latest class to override the method or member.