5

I would like to make it clear once and for all.

I'm pretty sure I know when to use self::MY_CONST and SomeClass::MY_CONST but it's unclear when to use static::MY_CONST.

You use self::MY_CONST…

…when you refer to a constant that is defined in the same class where you call it.

Example:

class Foo 
{
    const MY_CONST = 123;

    public function example() 
    {
        echo self::MY_CONST;
    }
}

You use AnotherClass::MY_CONST…

…when you refer to a constant that is defined in different class that the one from where you call it.

Example:

class Bar
{
    const MY_CONST = 123;
}

class Foo 
{
    public function example() 
    {
        echo Bar::MY_CONST;
    }
}

You use static::MY_CONST…

…when? I don't know. In terms of referring constants using static makes no sense to me. Please provide a valid reason or confirm that self:: and SomeClass:: examples are sufficient.

edit: My question is not a duplicate. I don't ask about $this at all. Don't mark this as a duplicate.

Matt Komarnicki
  • 5,198
  • 7
  • 40
  • 92
  • 2
    Possible duplicate of [Difference between static:: and $this::](https://stackoverflow.com/questions/24476194/difference-between-static-and-this) – Poul Kruijt Aug 21 '18 at 10:09
  • Hi @PierreDuc, I don't think this is a duplicate. I have a clear question that has nothing to do with `$this`. – Matt Komarnicki Aug 21 '18 at 10:10
  • Possible duplicate of [What exactly are late static bindings in PHP?](https://stackoverflow.com/questions/1912902/what-exactly-are-late-static-bindings-in-php) – lxg Aug 21 '18 at 10:27
  • @slick: It is a duplicate, but not of the one selected by PierreDuc. There are [many other questions about late static binding](https://stackoverflow.com/search?q=php+late+static+binding), though. Which you might have found doing some research. – lxg Aug 21 '18 at 10:29
  • I think @IMSoP gave a nice example where I can see some difference. My conclusion is that if I operate only within a class with no inheritance I can keep using `self::` otherwise `static::` would be a way to go, right? – Matt Komarnicki Aug 21 '18 at 10:31

2 Answers2

4

The static keyword is needed for something called "Late Static Binding" (see also What exactly are late static bindings in PHP?). The manual page on that topic is not the clearest, but this sentence is key:

"Late binding" comes from the fact that static:: will not be resolved using the class where the method is defined but it will rather be computed using runtime information.

Effectively, static:: is similar to $this, in that it resolves to the class where the code is running, which might be a sub-class of the class where the code is written.

Let's use your example of self::, and add a sub-class:

class Foo 
{
    const MY_CONST = 123;

    public function example() 
    {
        echo self::MY_CONST;
    }
}

class Bar extends Foo
{
    const MY_CONST = 456;
}

$bar = new Bar;
$bar->example();

This will output 123, because the self:: in the definition always refers to Foo, regardless of how you call it.

However, if we change to use late static binding:

class Foo 
{
    const MY_CONST = 123;

    public function example() 
    {
        echo static::MY_CONST;
    }
}

class Bar extends Foo
{
    const MY_CONST = 456;
}

$bar = new Bar;
$bar->example();

Now it will echo 456, because the static:: resolves to the class we were actually using at runtime when we made the call, which was Bar, and Bar::MY_CONST has a different value.

IMSoP
  • 89,526
  • 13
  • 117
  • 169
  • Wow, it's clearer now. So basically it looks like using `static` is a way to go when you have inheritance, but when you operate only within a single class, the `self` is sufficient, right? – Matt Komarnicki Aug 21 '18 at 10:30
0

This example will show you all the difference:

<?php

class A
{
    const TEST = 'A';

    static function echoSelf()
    {
        echo self::TEST . PHP_EOL;
    }

    static function echoStatic()
    {
        echo static::TEST . PHP_EOL;
    }
}

class B extends A
{
    const TEST = 'B';
}

echo 'Using self:' .PHP_EOL;
A::echoSelf(); // A
B::echoSelf(); // A

echo 'Using static:' .PHP_EOL;
A::echoStatic(); // A
B::echoStatic(); // B

Enjoy ;)

Damian Dziaduch
  • 2,107
  • 1
  • 15
  • 16