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

6

210

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
Damascus answered 29/7, 2012 at 14:41 Comment(1)
@deceze: That's a similar question, but it isn't a duplicate. This one asks about using the keywords with properties, while that asks about using them with constructors.Morisco
M
263

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.

Morisco answered 29/7, 2012 at 14:52 Comment(4)
You might very easily redeclare in the child class, the parent class might be a default value that the child class uses unless they re-declare. If you are in the parent class, I guess it is safe to use self::, and if in a child class, you could come up with an argument to use either one, but self:: will also work if you dont expect to re-declare ever.Herries
run this <?php class Foo { public static $bar = 1234; public static function a( ) { echo 'static'.static::$bar; echo 'self'.self::$bar; } } class Bar extends Foo { public static $bar = 4321; } (new Bar())->a(); ?>Valrievalry
The first two paragraph wording is confusing, has an ambiguous pronoun, "it", and is also redunant, as a later paragraphs explains the same information more clearly. I suggest replacing the first two paragraphs with the later paragraph that starts with "In the above scenario" to the top. That way the bottom line, cut-to-the-chase answer is at the top. It's clear and easy to follow.Capitalism
Another way to think about this: self::$abc, when used inside class Foo is the same as saying Foo::$abc. It won't be affected by any re-declaration of $abc in a subclass. AFAIK, the only reason to use self is as a shorthand, to avoid using the class name Foo, which may be longer. [It also means you can change the classname without changing all those places - but that isn't much of a reason IMHO.] (PHP's choice of names is unfortunate, and seems backwards; "static" is the one that can change - which is opposite to the colloquial meaning of the natural-language word "static".)Mydriatic
E
62

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
Evade answered 26/9, 2020 at 0:49 Comment(0)
K
35

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();
Kwan answered 15/7, 2020 at 14:40 Comment(1)
Very straight forward and not confusing example.Holliholliday
A
12

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.

Argillite answered 19/11, 2019 at 20:41 Comment(0)
N
12

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)
Nessa answered 24/8, 2020 at 13:8 Comment(0)
R
1

Short version

Both self:: and static:: refer to static properties/functions in a parent class. But where self:: gets something from the class that defines the function, static:: gets something from the class that executes the function.

Example

class Parent
{
    static $best_afternoon = ' take a nap.';
    static $opinion_of_plan = ' enjoy';

    $name;

    function __construct($name){$this->name = $name;}

    function plan()
    {
        echo $this->name . ' will' .  self::$best_afternoon;
    }
    function nap()
    {
        echo $this->name . ' will' . static::$opinion_of_plan . ' it.';
    }
}
class Child extends Parent
{
    static $best_afternoon = ' run around.';
    static $opinion_of_plan = ' dislike';
}
$mother = new Parent('Alice');
$son = new Child('Ben');

The Child class has its own best-afternoon and opinion values, but every Child inherits both the plan and nap functions from the Parent class. But while the nap function gets the overridden (late-bound) values using static::, the plan function references its original context because it uses self:: instead.

$mother->plan(); //> "Alice will take a nap."
$son->plan(); //> "Ben will take a nap."

$mother->nap(); //> "Alice will enjoy it."
$son->nap(); //> "Ben will dislike it."

Of course if children had their own plan function, calling $son->plan() might return something completely different. And of course asking Ben directly what was the best afternoon would still return the overridden value from the Child class.

echo $mother::$best_afternoon; //> " take a nap."
echo $son::$best_afternoon; //> " run around."
Ridotto answered 14/9, 2023 at 3:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.