Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Right way to instantiate class in PHP

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.

like image 585
AlFra Avatar asked Jul 09 '14 12:07

AlFra


People also ask

What is the correct way of initiating a PHP class?

class ¶ Basic class definitions begin with the keyword class , followed by a class name, followed by a pair of curly braces which enclose the definitions of the properties and methods belonging to the class. The class name can be any valid label, provided it is not a PHP reserved word.

How do you instantiate the class?

Instantiating a ClassThe new operator requires a single, postfix argument: a call to a constructor. The name of the constructor provides the name of the class to instantiate. The new operator returns a reference to the object it created.

Can you create a class in PHP?

Classes are nothing without objects! We can create multiple objects from a class. Each object has all the properties and methods defined in the class, but they will have different property values. Objects of a class is created using the new keyword.

Why do we instantiate a class?

A class can also be instantiated to create an object, a concrete instance of the class. The object is an executable file that can run on a computer. One use of instantiation is data modeling and programming before OOP.


1 Answers

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.

like image 173
Andy J. Avatar answered Sep 29 '22 23:09

Andy J.