Usando __construct() en PHP 7

El método mágico __construct () representa un concepto de constructor PHP similar al de otros lenguajes OO. Permite a los desarrolladores aprovechar el proceso de creación de objetos. Las clases que tienen el método __construct() declarado, lo llaman en cada objeto recién creado. Esto nos permite lidiar con cualquier inicialización que el objeto pueda necesitar antes de usarlo.
El siguiente fragmento de código muestra el uso más simple posible del método __construct():

<?php
class User
{
public function __construct()
{
var_dump('__construct');
}
}
new User;
new User();

Ambas instancias de usuario producirán la misma cadena (11) de salida «__construct» a la pantalla. El ejemplo más complejo podría incluir parámetros de constructor. Considere el siguiente fragmento de código:

<?php
class User
{
protected $name;
protected $age;
public function __construct($name, $age)
{
$this->name = $name;
$this->age = $age;
var_dump($this->name);
var_dump($this->age);
}
}
new User; #1
new User('John'); #2
new User('John', 34); #3
new User('John', 34, 4200.00); #4

Aquí, vemos un método __construct () que acepta los dos parámetros: $name y $age.
Justo después de la definición de la clase Usuario, tenemos cuatro intentos diferentes de inicialización de objetos.
El intento n.° 3 es el único intento de inicialización válido. Los intentos n.° 1 y n.° 2 activan el siguiente error:

Warning: Missing argument 1 for User::__construct() // #1
Warning: Missing argument 2 for User::__construct() // #1 & #2

El intento n.° 4, aunque no sea válido, no activa el error. PHP no genera un mensaje de error, a diferencia de otros métodos, cuando __construct() se reemplaza con parámetros adicionales.
Otro caso interesante para el método __construct() es con las clases padre. Consideremos el siguiente ejemplo:

<?php
class User
{
protected $name;
protected $age;
public function __construct($name, $age)
{
$this->name = $name;
$this->age = $age;
}
}
class Employee extends User
{
public function __construct($employeeName, $employeeAge)
{
var_dump($this->name);
var_dump($this->age);
}
}
new Employee('John', 34);

La salida del código anterior es la siguiente:

NULL NULL

La razón de esto es que los constructores principales no se llaman implícitamente si la clase secundaria define un constructor. Para activar el constructor padre, necesitamos ejecutar parent :: __ construct() dentro del constructor hijo. Modifiquemos nuestra clase Employee para hacer justamente eso:

class Employee extends User
{
public function __construct($employeeName, $employeeAge)
{
parent::__construct($employeeName, $employeeAge);
var_dump($this->name);
var_dump($this->age);
}
}

Esta será la salida ahora:

string(4) "John" int(34)

Echemos un vistazo al siguiente ejemplo:

<?php
class User
{
public function __construct()
{
var_dump('__construct');
}
public static function hello($name)
{
return 'Hello ' . $name;
}
}
echo User::hello('John');

Aquí, tenemos una clase de usuario simple con un mágico __construct() y un método estático hello(). Justo después de la definición de la clase, tenemos una llamada al método estático hello().
Esto no activa el método __construct().
El único resultado del ejemplo anterior es el siguiente:

Hello John

El método __construct() solo se activa cuando se inicia un objeto a través de la nueva palabra clave.
Queremos mantener nuestro método __construct(), así como otros métodos mágicos, solo bajo el modificador de acceso público. Sin embargo, si la situación lo exige, también podemos incluir el modificador de acceso final.
Considere el siguiente ejemplo:

<?php
class User
{
public final function __construct($name)
{
var_dump($name);
}
}
class Director extends User
{
}
class Employee extends User
{
public function __construct($name)
{
var_dump($name);
}
}
new User('John'); #1
new Director('John'); #2
new Employee('John'); #3

Por inusual que sea, los intentos de inicialización n.° 1 y n.° 2 funcionarían incluso con el modificador de acceso final. Esto se debe a que # 1 crea una instancia de la clase de Usuario original que define el método final __construct (), y # 2 crea una instancia de la clase Director vacía que no intenta implementar su propio método __construct (). El intento de inicialización # 3 fallaría, resultando en el siguiente error:

Fatal error: Cannot override final method User::__construct()

Esta es realmente la base de modificadores de acceso y anulaciones, no específica del método mágico __construct () en sí. Sin embargo, vale la pena saber que es posible usar el modificador final con el constructor, ya que podría ser útil.
Además de crear instancias de objetos simples, el uso práctico del método __construct () en OOP se presenta en forma de inyección de dependencia. Hoy en día, generalmente se acepta que inyectar dependencias es una práctica recomendada para tratar las dependencias. Si bien las dependencias se pueden inyectar en un objeto a través de varios métodos de establecimiento, el uso del método __construct () prevalece como un enfoque dominante con algunas de las principales plataformas PHP, como Magento.
El siguiente bloque de código muestra el método __construct () del archivo vendor/magento/module-gift-message/Model/Save.php de Magento:

public function __construct(
\Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
\Magento\GiftMessage\Model\MessageFactory $messageFactory,
\Magento\Backend\Model\Session\Quote $session,
\Magento\GiftMessage\Helper\Message $giftMessageMessage
) {
$this->productRepository = $productRepository;
$this->_messageFactory = $messageFactory;
$this->_session = $session;
$this->_giftMessageMessage = $giftMessageMessage;
}

Aquí se pasan varias dependencias a través del método __construct (), que parece un paso adelante respecto a los ejemplos anteriores. Aun así, la mayoría de los métodos __construct () de Magento son mucho más robustos que esto, transmitiendo decenas de parámetros al objeto.
Podríamos resumir fácilmente la función del método __construct () como una especie de firma de clase que representa cómo un consumidor debe crear una instancia completa de un objeto en particular.

Comparte