php – Differences in using $this, self, static and parent

Question:

I have a question about the "proper" use of $this , self , static and parent in some specific scenarios. I know the meaning and theoretical use of each one:

  • $this : basically references the object instance. Serves for non-static properties and methods. Cannot be used with constants

  • static : same as $this, but used for methods, static properties, and constants

  • self : used for methods, static properties, and constants. In practice in a class hierarchy it references the class in
    who that self is being written

  • parent : will reference the parent class. Can be used with methods, static properties and constants


In the code below, the idea of ​​using parent was to give visibility that the called method is an "external" method, or rather, inherited. Would that be correct?

<?php

class Pessoa{     

    private $nome;
    private $idade;
    private $sexo;  

    protected function setNome($nome)
    {
        if(is_string($nome)) {
            $this->nome = $nome;
            return true;
        }

        return false;
    }

    protected function setIdade($idade)
    {
        if(is_int($idade)) {
            $this->idade = $idade;
            return true;
        }

        return false;
    }

    protected function setSexo($sexo)
    {
        if($sexo == 'M' || $sexo = "F") {
            $this->sexo = $sexo;
            return true;
        }

        return false;
    }

    public function getNome()
    {
        return $this->nome;
    }

    public function getIdade()
    {
        return $this->idade;
    }

    public function getSexo()
    {
        return $this->sexo;
    }
} 

class Funcionario extends Pessoa
{ 
    private $empresa;
    private $salario;

    public function __construct($nome, $idade, $sexo, $empresa, $salario)
    {
        parent::setNome($nome);
        parent::setIdade($idade);
        parent::setSexo($sexo);
        $this->empresa = $empresa;
        $this->salario = $salario;
    }

    public function getEmpresa()
    {
        return $this->empresa;
    }

    public function getSalario()
    {
        return $this->salario;
    }
}

$funcionario = new Funcionario("Yuri", "19", "Masculino", "Tam", "3000");

echo $funcionario->getNome() . ' Trabalha na: ' . $funcionario->getEmpresa() . ' e ganha ' . $funcionario->getSalario();

Now a macro question: is there any recipe that suggests when it's better to use $this , self , static or parent ?

Answer:

The recipe is: use the one that should be used .

As you described, the four do different things, so just use the correct one, there is no better.

parent

References the parent class that was inherited by the current class. Basically it was created so that you don't need, inside the child class, to be explicit which is the parent class from which the method will be called, access the attribute, constant, etc.

<?php

class A {
    function example() {
        echo "I am A::example() and provide basic functionality.<br />\n";
    }
}

class B extends A {
    function example() {
        echo "I am B::example() and provide additional functionality.<br />\n";
        parent::example();
    }
}

$b = new B;

// This will call B::example(), which will in turn call A::example().
$b->example();

// Saída:
// I am B::example() and provide additional functionality.
// I am A::example() and provide basic functionality.

Example taken from the official documentation . See it working on Ideone | Rep.it

In the code above, the example method is rewritten in B , however, its reference in A remains through parent . The only difference in making A::example() here is that you don't need to specify the name of the inherited class. If the name of class A were changed to W , it would only be enough to change in the declaration of B , class B extends W , and not in the entire code. The result is exactly the same.

this

Reference to the instance itself. Everything belonging to the instance will be available in $this . Static and constant methods belong to the class itself and therefore are not accessible on this object (in PHP). Adapting the previous example a little, we can do:

<?php

class A {
    function example() {
        echo "I am A::example() and provide basic functionality.<br />\n";
    }
}

class B extends A {
    function example() {
        echo "I am B::example() and provide additional functionality.<br />\n";
    }

    function main() {
        $this->example();
        parent::example();
    }
}

$b = new B;

// This will call B::example(), which will in turn call A::example().
$b->main();

// Saída:
// I am B::example() and provide additional functionality.
// I am A::example() and provide basic functionality.

See it working on Ideone | Rep.it

self

The reference in self always points to the class where it is used and that is the difference for static . When using self in A , the reference will be to class A and when used in B the reference will be to B. This influences a lot, for example, when you want to define the return in a method:

<?php

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

class B extends A {

}

$b = new B();
$obj = $b->example();

echo get_class($obj), PHP_EOL;

// Saída:
// A

See it working on Ideone | Rep.it

Note that setting the return to self will return an instance object of A, not B.

static

Similar to self , static will always refer to the class of the instance used . Sometimes the behavior of static is summarized as a lazy self , as it doesn't set the reference on the fly. Running the same example above, changing self to static , we have:

<?php

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

class B extends A {

}

$b = new B();
$obj = $b->example();

echo get_class($obj), PHP_EOL;

// Saída:
// B

See it working on Ideone | Rep.it

Even if static is used in class A, the return will be a new instance of B, because new static was invoked from an instance of B and, as said, static always refers to the class of the current instance.

Summing up…

  • parent should be used when you need to reference the parent class;
  • this must be used to refer to the current instance;
  • self must be used to refer to the class where it is applied;
  • static must be used to refer to the class of the instance where it is applied.
Scroll to Top