PHP

PHP

Tutorial PHP: Constructores y destructores

Aprende a usar PHP métodos __construct() y __destruct() para inicializar y destruir objetos eficazmente, optimizando aplicaciones.

Aprende PHP y certifícate

Método __construct()

El método __construct() es la función especial que PHP utiliza como constructor de una clase. Se invoca automáticamente al crear una nueva instancia, permitiendo inicializar propiedades o ejecutar código necesario antes de que el objeto sea usado.

En PHP, se define el constructor dentro de una clase utilizando el nombre __construct(). A continuación, se muestra un ejemplo básico:

<?php

class Usuario
{
    public $nombre;

    public function __construct($nombre)
    {
        $this->nombre = $nombre;
        echo "Usuario {$this->nombre} creado.\n";
    }
}

$usuario = new Usuario("María");

En este ejemplo, al crear un nuevo objeto de la clase Usuario, el constructor recibe un parámetro $nombre y lo asigna a la propiedad $nombre. Además, imprime un mensaje indicando que el usuario ha sido creado.

El constructor puede aceptar tantos parámetros como sean necesarios para inicializar el objeto. Esto permite pasar valores personalizados al crear instancias de la clase.

Es posible definir valores por defecto en los parámetros del constructor. Por ejemplo:

<?php

class Producto
{
    public $nombre;
    public $precio;

    public function __construct($nombre = "Producto Genérico", $precio = 0.0)
    {
        $this->nombre = $nombre;
        $this->precio = $precio;
        echo "Producto {$this->nombre} con precio {$this->precio} creado.\n";
    }
}

$producto = new Producto();
$productoPersonalizado = new Producto("Libro", 15.99);

En este caso, si no se proporcionan argumentos al crear un nuevo Producto, se utilizarán los valores por defecto. Esto aporta flexibilidad en la inicialización de objetos.

Cuando se trabaja con herencia, el constructor de la clase hija puede llamar al constructor de la clase padre utilizando parent::__construct(). Esto es útil para asegurar que las propiedades heredadas se inicialicen correctamente. Ejemplo:

<?php

class Vehiculo
{
    public $marca;

    public function __construct($marca)
    {
        $this->marca = $marca;
        echo "Vehículo de marca {$this->marca} creado.\n";
    }
}

class Coche extends Vehiculo
{
    public $modelo;

    public function __construct($marca, $modelo)
    {
        parent::__construct($marca);
        $this->modelo = $modelo;
        echo "Coche modelo {$this->modelo} creado.\n";
    }
}

$coche = new Coche("Toyota", "Corolla");

En este ejemplo, Coche extiende de Vehiculo y su constructor llama a parent::__construct($marca) para inicializar la propiedad $marca.

A partir de PHP 8.0, se introdujo la promoción de propiedades del constructor, que permite declarar y asignar propiedades directamente en la firma del constructor. Esto simplifica el código y mejora su legibilidad:

<?php

class Punto
{
    public function __construct(
        public float $x = 0.0,
        public float $y = 0.0
    ) {
        echo "Punto en coordenadas ({$this->x}, {$this->y}) creado.\n";
    }
}

$punto = new Punto(5.5, 10.2);

Aquí, las propiedades $x y $y se declaran y asignan en el constructor, reduciendo la cantidad de código necesario.

El método __construct() es esencial para asegurar que los objetos se crean en un estado válido y listo para su uso. Al inicializar correctamente las propiedades y ejecutar cualquier lógica necesaria, se mejora la confiabilidad y consistencia de las aplicaciones desarrolladas en PHP.

Método __destruct()

El método __destruct() es una función especial en PHP que actúa como destructor de una clase. Se invoca automáticamente cuando un objeto es destruido o liberado de la memoria, permitiendo ejecutar código de limpieza o liberar recursos antes de que el objeto deje de existir.

El destructor se define dentro de una clase utilizando el nombre __destruct(), sin parámetros. A continuación, se muestra un ejemplo básico:

<?php

class ArchivoTemporal
{
    private $ruta;

    public function __construct($nombre)
    {
        $this->ruta = "/tmp/{$nombre}";
        file_put_contents($this->ruta, "Contenido temporal\n");
        echo "Archivo temporal {$this->ruta} creado.\n";
    }

    public function __destruct()
    {
        if (file_exists($this->ruta)) {
            unlink($this->ruta);
            echo "Archivo temporal {$this->ruta} eliminado.\n";
        }
    }
}

$archivo = new ArchivoTemporal("datos.txt");
echo "Procesando el archivo temporal...\n";

En este ejemplo, la clase ArchivoTemporal crea un archivo en el constructor y lo elimina en el destructor. Al finalizar el script o cuando el objeto es destruido, el método __destruct() se ejecuta automáticamente, garantizando que el archivo temporal se elimine.

El destructor es útil para liberar recursos externos como archivos, conexiones de base de datos o sockets de red. Esto ayuda a prevenir fugas de recursos y asegura que los recursos se limpien adecuadamente.

Es importante tener en cuenta que el destructor se invoca en los siguientes casos:

  • Cuando el script termina su ejecución.
  • Cuando se elimina el último referente al objeto (por ejemplo, al asignar null a la variable).
  • Cuando el objeto se sale de su alcance (en entornos sin recolector de basura).

Otro ejemplo común es el cierre de conexiones de base de datos:

<?php

class ConexionBD
{
    private $conexion;

    public function __construct($dsn, $usuario, $contraseña)
    {
        try {
            $this->conexion = new PDO($dsn, $usuario, $contraseña);
            echo "Conexión a la base de datos establecida.\n";
        } catch (PDOException $e) {
            echo "Error de conexión: " . $e->getMessage() . "\n";
        }
    }

    public function __destruct()
    {
        $this->conexion = null;
        echo "Conexión a la base de datos cerrada.\n";
    }
}

$bd = new ConexionBD('mysql:host=localhost;dbname=test', 'root', 'password');
// Operaciones con la base de datos

En este caso, el destructor asigna null a la propiedad $conexion, cerrando la conexión a la base de datos. Esto es especialmente útil en scripts largos o aplicaciones que manejan múltiples conexiones.

Es posible forzar la ejecución del destructor antes del final del script destruyendo el objeto manualmente:

<?php

$recurso = new RecursoExterno();
// Uso del recurso
unset($recurso); // El destructor se ejecuta aquí

echo "El objeto ha sido destruido.\n";

Al utilizar unset($recurso), se elimina la referencia al objeto y el destructor se ejecuta inmediatamente. Esto es útil cuando se necesita liberar recursos en un punto específico del código.

En el contexto de herencia, si una clase hija define un destructor, es aconsejable llamar al destructor de la clase padre para asegurar que todos los recursos se liberen correctamente:

<?php

class Logger
{
    protected $archivo;

    public function __construct($ruta)
    {
        $this->archivo = fopen($ruta, 'a');
    }

    public function __destruct()
    {
        fclose($this->archivo);
        echo "Archivo de log cerrado.\n";
    }
}

class LoggerDetallado extends Logger
{

    public function __destruct()
    {
        // Acciones adicionales antes de cerrar
        echo "Escribiendo resumen final.\n";
        parent::__destruct();
    }
}

$logger = new LoggerDetallado("app.log");
// Registro de eventos

En este ejemplo, LoggerDetallado sobrescribe el destructor para realizar acciones adicionales y luego llama a parent::__destruct() para asegurar que el archivo de log se cierre apropiadamente.

Es esencial utilizar el método __destruct() cuando se manejan recursos que no son gestionados automáticamente por PHP, como conexiones o archivos abiertos. De esta manera, se garantiza que la aplicación maneje los recursos de forma eficiente y segura.

Inicialización de propiedades

La inicialización de propiedades en una clase PHP es un paso crucial para garantizar que los objetos comiencen en un estado consistente y válido. Existen varias formas de asignar valores iniciales a las propiedades, más allá del constructor, aprovechando características del lenguaje que aportan claridad y eficiencia al código.

Una forma común de inicializar propiedades es asignando valores por defecto en su declaración dentro de la clase. Esto permite establecer un estado inicial sin necesidad de incluir lógica adicional en el constructor:

<?php

class Configuracion
{
    public string $idioma = 'es';
    public int $elementosPorPagina = 10;
    public bool $modoOscuro = false;
}

$config = new Configuracion();
echo "Idioma: {$config->idioma}\n";
echo "Elementos por página: {$config->elementosPorPagina}\n";
echo "Modo oscuro: " . ($config->modoOscuro ? 'Activado' : 'Desactivado') . "\n";

En este ejemplo, las propiedades $idioma, $elementosPorPagina y $modoOscuro tienen valores iniciales asignados directamente en su declaración. Al crear una instancia de Configuracion, estos valores están disponibles inmediatamente sin necesidad de un constructor.

Con la introducción de los tipos de propiedad en PHP 7.4, es posible declarar el tipo de las propiedades y asignarles valores por defecto que sean compatibles con dichos tipos. Esto mejora la seguridad y la legibilidad del código:

<?php

class Usuario
{
    public string $nombre = 'Anónimo';
    public ?string $email = null;
    public array $roles = [];
}

$usuario = new Usuario();
echo "Nombre: {$usuario->nombre}\n";
echo "Email: " . ($usuario->email ?? 'No asignado') . "\n";
echo "Roles: " . implode(', ', $usuario->roles) . "\n";

Aquí, las propiedades tipadas garantizan que los valores asignados sean del tipo especificado, y los valores por defecto proporcionan un estado inicial consistente.

Las propiedades estáticas también pueden ser inicializadas en su declaración. Dado que pertenecen a la clase y no a las instancias, es útil para valores compartidos entre todos los objetos de la misma clase:

<?php

class Sesion
{
    public static int $usuariosActivos = 0;

    public function __construct()
    {
        self::$usuariosActivos++;
        echo "Nuevo usuario inició sesión. Total: " . self::$usuariosActivos . "\n";
    }

    public function __destruct()
    {
        self::$usuariosActivos--;
        echo "Un usuario cerró sesión. Total: " . self::$usuariosActivos . "\n";
    }
}

$sesion1 = new Sesion();
$sesion2 = new Sesion();

unset($sesion1);

En este caso, la propiedad estática $usuariosActivos se inicializa a 0 y se incrementa o decrementa según se creen o destruyan instancias de Sesion. Esto permite llevar un conteo global de usuarios activos.

La inicialización tardía de propiedades puede ser útil cuando el valor inicial depende de una condición o cálculo complejo. En lugar de asignar el valor en la declaración o en el constructor, se puede utilizar un método específico o un getter con lazy loading:

<?php

class Reporte
{
    private ?array $datos = null;

    public function obtenerDatos(): array
    {
        if ($this->datos === null) {
            echo "Cargando datos...\n";
            $this->datos = $this->cargarDatos();
        }
        return $this->datos;
    }

    private function cargarDatos(): array
    {
        // Simulación de carga de datos intensiva
        sleep(2);
        return ['ventas' => 1000, 'ingresos' => 50000];
    }
}

$reporte = new Reporte();
$datos = $reporte->obtenerDatos();
echo "Ventas: {$datos['ventas']}\n";
echo "Ingresos: {$datos['ingresos']}\n";

Con este enfoque, la propiedad $datos se inicializa solo cuando es necesaria, optimizando el uso de recursos. La inicialización tardía es especialmente beneficiosa cuando el proceso de obtención del valor es costoso en términos de tiempo o recursos.

Es importante mencionar que, a partir de PHP 8.1, se introdujeron las propiedades de solo lectura utilizando la palabra clave readonly. Estas propiedades deben ser inicializadas en la declaración o en el constructor, ya que no pueden modificarse posteriormente:

<?php

class Pedido
{
    public readonly int $numero;
    public readonly DateTime $fecha;

    public function __construct(int $numero)
    {
        $this->numero = $numero;
        $this->fecha = new DateTime();
    }
}

$pedido = new Pedido(12345);
echo "Pedido Nº {$pedido->numero} realizado el {$pedido->fecha->format('d-m-Y H:i')}\n";

Las propiedades readonly garantizan que su valor no cambiará una vez asignado, aportando mayor integridad al estado del objeto.

En situaciones donde se requiere validación o procesamiento adicional al asignar valores a las propiedades, es recomendable utilizar métodos setters. Esto permite centralizar la lógica y asegurar que las propiedades reciben valores válidos:

<?php

class CuentaBancaria
{
    private float $saldo = 0.0;

    public function depositar(float $monto): void
    {
        if ($monto <= 0) {
            throw new InvalidArgumentException("El monto a depositar debe ser positivo.\n");
        }
        $this->saldo += $monto;
        echo "Depósito de {$monto} realizado. Saldo actual: {$this->saldo}\n";
    }

    public function obtenerSaldo(): float
    {
        return $this->saldo;
    }
}

$cuenta = new CuentaBancaria();
$cuenta->depositar(100.50);
echo "Saldo final: {$cuenta->obtenerSaldo()}\n";

Al encapsular la inicialización y modificación de la propiedad $saldo, se asegura que el objeto CuentaBancaria mantiene un estado coherente y seguro.

Por último, es buena práctica combinar diferentes métodos de inicialización para lograr un código limpio y mantenible. La elección entre inicializar una propiedad en su declaración, en el constructor, o mediante métodos específicos dependerá del contexto y las necesidades de la aplicación.

La correcta inicialización de propiedades es fundamental para el diseño de clases robustas y fiables en PHP. Al aprovechar las características del lenguaje y aplicar buenas prácticas, se contribuye al desarrollo de aplicaciones más seguras y eficientes.

CONSTRUYE TU CARRERA EN IA Y PROGRAMACIÓN SOFTWARE

Accede a +1000 lecciones y cursos con certificado. Mejora tu portfolio con los certificados de CertiDevs.

20 % DE DESCUENTO

Plan mensual

19.00 /mes

15.20 € /mes

Precio normal mensual: 19 €
58 % DE DESCUENTO

Plan anual

10.00 /mes

8.00 € /mes

Ahorras 132 € al año
Precio normal anual: 120 €
Aprende PHP online

Todas las lecciones de PHP

Accede a todas las lecciones de PHP y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Php

PHP

Introducción Y Entorno

Instalación Y Primer Programa De Php

PHP

Introducción Y Entorno

Tipos De Datos, Variables Y Constantes

PHP

Sintaxis

Operadores Y Expresiones

PHP

Sintaxis

Estructuras De Control

PHP

Sintaxis

Funciones Y Llamada De Funciones

PHP

Sintaxis

Cadenas De Texto Y Manipulación

PHP

Sintaxis

Manejo De Números

PHP

Sintaxis

Manejo De Fechas Y Tiempo

PHP

Sintaxis

Manejo De Arrays

PHP

Sintaxis

Introducción A La Poo En Php

PHP

Programación Orientada A Objetos

Clases Y Objetos

PHP

Programación Orientada A Objetos

Constructores Y Destructores

PHP

Programación Orientada A Objetos

Herencia

PHP

Programación Orientada A Objetos

Encapsulación

PHP

Programación Orientada A Objetos

Polimorfismo

PHP

Programación Orientada A Objetos

Interfaces

PHP

Programación Orientada A Objetos

Traits

PHP

Programación Orientada A Objetos

Namespaces

PHP

Programación Orientada A Objetos

Autoloading De Clases

PHP

Programación Orientada A Objetos

Manejo De Errores Y Excepciones

PHP

Programación Orientada A Objetos

Manejo De Archivos

PHP

Programación Orientada A Objetos

Patrones De Diseño

PHP

Programación Orientada A Objetos

Introducción A Los Formularios En Php

PHP

Formularios

Procesamiento De Datos De Formularios

PHP

Formularios

Manejo De Archivos En Formularios

PHP

Formularios

Redirecciones Y Retroalimentación Al Usuario

PHP

Formularios

Formularios Dinámicos Y Separación De Lógica

PHP

Formularios

Introducción A La Persistencia En Php

PHP

Persistencia

Conexión A Bases De Datos

PHP

Persistencia

Consultas Y Operaciones Crud

PHP

Persistencia

Gestión De Transacciones

PHP

Persistencia

Manejo De Errores Y Excepciones En Base De Datos

PHP

Persistencia

Patrones De Acceso A Datos

PHP

Persistencia

Concepto De Sesiones En Php

PHP

Sesiones Y Cookies

Configuración De Sesiones

PHP

Sesiones Y Cookies

Cookies

PHP

Sesiones Y Cookies

Manejo Avanzado De Sesiones Y Cookies

PHP

Sesiones Y Cookies

Principales Vulnerabilidades En Php

PHP

Seguridad

Seguridad En Formularios Y Entrada De Datos

PHP

Seguridad

Protección Frente A Inyección Sql

PHP

Seguridad

Gestión De Contraseñas Y Cifrado

PHP

Seguridad

Seguridad En Sesiones Y Cookies

PHP

Seguridad

Configuraciones De Php Para Seguridad

PHP

Seguridad

Introducción Al Testing En Php

PHP

Testing

Phpunit

PHP

Testing

Cobertura De Código En Testing

PHP

Testing

Test Doubles (Mocks, Stubs, Fakes, Spies)

PHP

Testing

Pruebas De Integración Y Funcionales

PHP

Testing

Accede GRATIS a PHP y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender el propósito del método __construct() y su uso.
  • Aprender cómo se inicializan las propiedades de una clase en PHP.
  • Entender el método __destruct() y su rol en la gestión de recursos.
  • Aplicar promociones de propiedades del constructor desde PHP 8.0.
  • Conocer el significado de propiedades readonly introducidas en PHP 8.1.
  • Implementar buenas prácticas para asegurar estados válidos al crear y destruir objetos.