Constructores y destructores en PHP
En programación orientada a objetos, un objeto debe tener sentido desde el momento en que se crea. Es habitual que necesitemos realizar operaciones iniciales —como asignar valores predeterminados o consultar una base de datos— justo al instanciarlo.
En una clase Empleado
, no tendría sentido crear un objeto sin definir su salario. Podríamos usar el constructor para conectarnos a la base de datos, recuperar el sueldo del empleado y asignarlo como propiedad del objeto.
Un constructor es un método especial que se ejecuta automáticamente al crear un objeto. Su nombre es siempre __construct()
:
class NombreClase {
public function __construct() {
// Acciones al crear el objeto
}
}
Podemos pasar valores al constructor para personalizar cada objeto:
class Empleado {
public function __construct($nombre, $salario) {
$this->nombre = $nombre;
$this->salario = $salario;
}
}
//Debemos indicar los parámetros en el momento de la creación del objeto:
$empleado1 = new Empleado("Ana", 1500);
- Es obligatorio pasar la misma cantidad de argumentos que se hayan definido en el constructor.
- También es posible definir valores por defecto para hacer que algunos parámetros sean opcionales.
Un destructor es otro método especial que se ejecuta automáticamente cuando el objeto se destruye, por ejemplo:
- al finalizar el script
- o cuando se llama explícitamente a
unset($objeto)
Su uso habitual es liberar recursos o guardar cambios finales:
class NombreClase {
public function __destruct() {
// Acciones al destruir el objeto
}
}
Vamos a ver un ejemplo completo:
<?php
include('librerias/conexion_bbdd.php');
$empleado1 = new Empleado(3457);
// Incrementamos dos veces el salario
$nuevo_salario = $empleado1->getSalario() * 1.10;
$empleado1->setSalario($nuevo_salario);
$nuevo_salario = $empleado1->getSalario() * 1.10;
$empleado1->setSalario($nuevo_salario);
class Empleado {
private $salario;
private $salarioInicial;
private $id;
public function __construct($numero_empleado) {
$sql = "SELECT salario FROM empleados WHERE id = $numero_empleado";
$datos = $GLOBALS['conexion']->query($sql);
$this->salario = $datos[0]['salario'];
$this->salarioInicial= $this->salario;
$this->id = $numero_empleado; // Corregido: era $this->$id
}
public function __destruct() {
$stmt = $GLOBALS['conexion']->prepare("UPDATE empleados SET salario = ? WHERE id = ?");
if ($stmt) {
$stmt->bind_param("di", $this->salario, $this->id);
// d = double (salario), i = integer (id)
$stmt->execute();
$stmt->close();
} else {
// Puedes loguear un error aquí si la preparación falla
error_log("Error al preparar la consulta en __destruct");
}
}
public function setSalario($valor) {
$this->salario = $valor;
}
public function getSalario() {
return $this->salario;
}
}
?>
- Se crea el objeto
$empleado1
- Recupera el sueldo del empleado 3457 de la base de datos y lo almacena en la propiedad
salario
. - También almacena el sueldo en la propiedad
salarioInicial
- Guarda el número de empleado en la propiedad
id
.
- Recupera el sueldo del empleado 3457 de la base de datos y lo almacena en la propiedad
- Se recupera el salario de
$empleado1
con el métodogetSalario
, se sube un 10% y se almacena de nuevo en el objeto con el métodosetSalario
. - Volvemos a realizar el paso anterior, incrementando otro 10% el salario del trabajador.
- El script finaliza, ejecutando el destructor del objeto
$empleado1
que realiza las siguientes acciones:- Comprueba si el salario del empleado se ha modificado durante la vida del objeto.
- En caso de haberse modificado, guarda el nuevo salario en la base de datos.
Observa que al realizar el guardado del salario en la base de datos con el destructor, en vez de hacerlo dentro del método setSalario, hemos evitado actualizar dos veces el mismo dato innecesariamente. De esta forma aumentamos la eficiencia del script.
NOTA: Para este ejemplo hemos utilizado un objeto almacenado en $GLOBALS['conexion']
que realiza todas las peticiones a la base de datos.