Right way to instantiate class in PHP

instance, instantiation, php

Solution

php.net says:

As of PHP 5.3.0, PHP implements a feature called late static bindings which can be used to reference the called class in a context of static inheritance.

More precisely, late static bindings work by storing the class named in the last "non-forwarding call". In case of static method calls, this is the class explicitly named (usually the one on the left of the :: operator); in case of non static method calls, it is the class of the object. A "forwarding call" is a static one that is introduced by self::, parent::, static::, or, if going up in the class hierarchy, forward_static_call(). The function get_called_class() can be used to retrieve a string with the name of the called class and static:: introduces its scope.

This feature was named "late static bindings" with an internal perspective in mind. "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. It was also called a "static binding" as it can be used for (but is not limited to) static method calls.

Limitations of self:

Static references to the current class like self:: or CLASS are resolved using the class in which the function belongs, as in where it was defined:

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        self::who();
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test();
?>

The above example will output: `A`

Late Static Bindings' usage:

Late static bindings tries to solve that limitation by introducing a keyword that references the class that was initially called at runtime. Basically, a keyword that would allow you to reference B from test() in the previous example. It was decided not to introduce a new keyword but rather use static that was already reserved.

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // Here comes Late Static Bindings
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test();
?>

The above example will output: `B`

`$this` keyword refers to current object and you cannot use it in static methods. When you say `return $this` it means that some method returns the same object on which it was invoked.

So the correct way would be using `static` keyword because if you say `return new static()` it refers to the class the method is currently in.

Problem

I am trying to create a method inside class, that will instantiate class that is currently in. But I would also need that from this method to work correctly in all extended classes. As I have learned from this thread, it's not good to use `self` keyword for this task. So obvious choice would be using `static` keyword. But, I've come across different method that also works. Example: ``` class SimpleClass { private $arg; public function __construct( $arg ){ $this->arg = $arg; } public function getArg(){return $this->arg;} public function setArg($arg){$this->arg = $arg;} public function staticInstance() { return new static( $this->arg ); } public function thisInstance() { return new $this( $this->arg ); } public function selfInstance() { return new self( $this->arg ); } } class ExtendedClass extends SimpleClass { } $c1 = 'SimpleClass'; $c2 = 'ExtendedClass'; $inst1 = new $c1('simple'); $inst2 = new $c2('extended'); $static_instance_1 = $inst1->staticInstance(); $this_instance_1 = $inst1->thisInstance(); $self_instance_1 = $inst1->selfInstance(); $static_instance_2 = $inst2->staticInstance(); $this_instance_2 = $inst2->thisInstance(); $self_instance_2 = $inst2->selfInstance(); echo "SimpleClass Instances\n"; echo get_class($static_instance_1); echo get_class($this_instance_1); echo get_class($self_instance_1); echo "ExtendedClass Instances\n"; echo get_class($static_instance_2); echo get_class($this_instance_2); echo get_class($self_instance_2); ``` As I can see from this example, both `staticInstance` and `thisInstance` produce "correct" results. Or do they? Can someone explain difference between these two methods and which one is "correct" one.

Original source

Related problems