585

I am converting a PHP 5.3 library to work on PHP 5.2. The main thing standing in my way is the use of late static binding like return new static($options); , if I convert this to return new self($options) will I get the same results?

What is the difference between new self and new static?

Mike
  • 12,359
  • 17
  • 65
  • 86

3 Answers3

1038

will I get the same results?

Not really. I don't know of a workaround for PHP 5.2, though.

What is the difference between new self and new static?

self refers to the same class in which the new keyword is actually written.

static, in PHP 5.3's late static bindings, refers to whatever class in the hierarchy you called the method on.

In the following example, B inherits both methods from A. The self invocation is bound to A because it's defined in A's implementation of the first method, whereas static is bound to the called class (also see get_called_class()).

class A {
    public static function get_self() {
        return new self();
    }

    public static function get_static() {
        return new static();
    }
}

class B extends A {}

echo get_class(B::get_self());  // A
echo get_class(B::get_static()); // B
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A
mleko
  • 11,650
  • 6
  • 50
  • 71
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • makes sense. I think the best bet is to pass the class name to the function that is using late static binding and then do return new $className($options); – Mike Mar 04 '11 at 18:25
  • 15
    You don't have to "pass" the class name, you can always do `get_called_class()`, which is effectively the same as `__CLASS__`, but LSB compatible. – shadowhand Mar 05 '11 at 00:13
  • 7
    get_called_class does not exist in – txwikinger Sep 21 '11 at 15:29
  • See below for get_class($this); – lucian303 Oct 11 '12 at 21:50
  • I have a similar situation... if you would like to take a look at it, I would really appreciate it. http://stackoverflow.com/questions/22107831/php-inheritance-dynamic-properties-and-new-static-constructor – Pepito Fernandez Mar 03 '14 at 16:16
  • get_class($this) does not work , these are static methods, there is no $this – David Mann Jan 31 '19 at 19:38
  • 6
    The function called as self::theFunction() behaves like "I will execute in the context of the class whom I physically belong to." and the function called as static::theFunction() behaves like "I will execute in the context of the class which has been actually called by the outside world". ( Assuming the inheritance scenario ). Thanks – Shubhranshu Mar 07 '19 at 07:40
  • In my head, I think of it as `new sticky` so to easily remember this concept :) – Damilola Olowookere Nov 05 '19 at 08:37
  • 10
    In my head, I just take whatever is intuitive, and make it opposite. You would think based on the naming, `self` would return itself, and `static` would return something that cannot be overridden... But lo and behold it's the opposite. I never cease to be impressed by PHP's naming, conventions, and overall style. -_- – ahnbizcad Nov 13 '19 at 19:47
  • 1
    I understand `self` as belonging intrinsically to a class (the one that has declared it) and `static` as "hold tight, we'll know the class when you get called". – wranvaud Mar 29 '22 at 23:11
  • Hi @BoltClock + 1 - when using static:: with inheritance, php will first look in the initial calling class and if it doesn't find it goes and looks for the parent class? THANKS IN ADVANCE –  Feb 03 '23 at 13:52
26

If the method of this code is not static, you can get a work-around in 5.2 by using get_class($this).

class A {
    public function create1() {
        $class = get_class($this);
        return new $class();
    }
    public function create2() {
        return new static();
    }
}

class B extends A {

}

$b = new B();
var_dump(get_class($b->create1()), get_class($b->create2()));

The results:

string(1) "B"
string(1) "B"
Marius Balčytis
  • 2,601
  • 20
  • 22
  • 19
    If the method isn't static then late static bindings become totally irrelevant. – BoltClock Oct 08 '12 at 20:33
  • 1
    For example, you could use it in "copy" method, where object is copied without using `clone`, but just by re-creating and setting the properties. `$copy = new static(); $copy->set($this->get()); return $copy;` – Marius Balčytis Nov 02 '12 at 01:27
  • 13
    @BoltClock Surely not? If you're calling an overridden static method from within an instance method of a subclass, then your choice of `self::` or `static::` is going to affect whether the base class's or subclass's version of that static method is used. In the absence of some reason to think that such a situation occurring inherently indicates bad practice (and I don't see any reason why this should be so), the choice between `self::` and `static::` is just as relevant within non-static methods as it is in static methods. Have I misunderstood your comment, or is one us simply wrong? – Mark Amery Feb 20 '14 at 17:34
  • 5
    @Mark Amery: Hmm I didn't think of that. You're absolutely right. I had assumed that no static methods were going to be called in the instance method in question, but based on your example, I can see how that would be a very naïve assumption. – BoltClock Feb 21 '14 at 04:42
  • Late Static Bindings doc => http://php.net/manual/en/language.oop5.late-static-bindings.php – DevWL Nov 03 '17 at 03:48
13

In addition to others' answers :

static:: will be computed using runtime information.

That means you can't use static:: in a class property because properties values :

Must be able to be evaluated at compile time and must not depend on run-time information.

class Foo {
    public $name = static::class;

}

$Foo = new Foo;
echo $Foo->name; // Fatal error

Using self::

class Foo {
    public $name = self::class;

}
$Foo = new Foo;
echo $Foo->name; // Foo

Please note that the Fatal error comment in the code i made doesn't indicate where the error happened, the error happened earlier before the object was instantiated as @Grapestain mentioned in the comments

Rain
  • 3,416
  • 3
  • 24
  • 40
  • 5
    Note the error is thrown on line 2 `public $name = static::class;`, not on line 7, as suggested by the example. The error says: "static::class cannot be used for compile-time class name resolution" which indicates the problem is not where you try to access the $name field, but far before, at the compilation of the PHP class. Line 7 (or 6) will not be reached in the first example. – Bence Szalai Feb 05 '19 at 20:25
  • Right, I did not mean to criticise, just clarified what confused me first in the hope it may help others. Helpful example anyway! – Bence Szalai Feb 05 '19 at 20:51