__get, __set, __isset, __unset
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy — lección 46 de 91.
PHP proporciona cuatro métodos mágicos que interceptan el acceso a propiedades: __get(), __set(), __isset() y __unset(). Estos se activan cuando intentas acceder a propiedades que no existen o son inaccesibles.
El método __get() se invoca al leer una propiedad inaccesible, mientras que __set() se encarga de escribir en una. Esto le permite crear propiedades dinámicas o añadir lógica cuando se accede a las propiedades:
<?php
class DynamicObject {
private array $data = [];
public function __get(string $name): mixed {
return $this->data[$name] ?? null;
}
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
}
$obj = new DynamicObject();
$obj->title = "Hello";
$obj->count = 42;
echo $obj->title . " - " . $obj->count;
Salida:
Hello - 42El método __isset() se activa mediante isset() o empty(), y __unset() responde a la función unset():
<?php
class DynamicObject {
private array $data = [];
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
public function __isset(string $name): bool {
return isset($this->data[$name]);
}
public function __unset(string $name): void {
unset($this->data[$name]);
}
}
$obj = new DynamicObject();
$obj->name = "Test";
echo isset($obj->name) ? "exists" : "missing";
Salida:
existsEstos métodos se utilizan comúnmente para crear contenedores de datos flexibles, implementar la carga diferida o construir objetos que se comporten como arreglos mientras mantienen una estructura orientada a objetos.
Desafío
FácilVamos a construir un gestor de configuración flexible que almacena ajustes dinámicamente utilizando métodos mágicos. Tu clase interceptará el acceso a las propiedades para gestionar los valores de configuración, comprobar si los ajustes existen y eliminarlos cuando sea necesario — todo sin definir explícitamente cada propiedad.
Organizarás tu código en dos archivos:
Config.php— Crea una claseConfigque utilice un array privado para almacenar los valores de configuración internamente. Implementa los cuatro métodos mágicos de propiedades:__get($name)— Devuelve el valor para la clave dada, o"undefined"si la clave no existe__set($name, $value)— Almacena el valor bajo la clave dada__isset($name)— Devuelve si la clave existe en la configuración__unset($name)— Elimina la clave de la configuración
count()que devuelva el número de ajustes almacenados.main.php— Incluye el archivo Config. Recibirás tres entradas: un nombre de ajuste, un valor de ajuste y un segundo nombre de ajuste. Crea una instancia deConfigy realiza estas operaciones:- Establece el primer ajuste con el valor dado
- Imprime si el primer ajuste existe usando
isset()— salida"exists"o"missing" - Imprime el valor del primer ajuste
- Imprime el recuento actual de ajustes
- Usa
unset()para eliminar el primer ajuste - Imprime si el primer ajuste existe ahora — salida
"exists"o"missing" - Imprime el valor del segundo ajuste (que nunca fue establecido)
Cada salida debe estar en su propia línea. Los métodos mágicos te permiten interactuar con tu objeto Config usando una sintaxis de propiedad natural como $config->theme = "dark" e isset($config->theme), aunque no se hayan definido propiedades reales.
Hoja de referencia
PHP proporciona cuatro métodos mágicos para interceptar el acceso a propiedades:
__get(string $name): mixed— Se llama al leer una propiedad inaccesible__set(string $name, mixed $value): void— Se llama al escribir en una propiedad inaccesible__isset(string $name): bool— Se activa medianteisset()oempty()__unset(string $name): void— Se activa medianteunset()
Ejemplo de __get() y __set():
<?php
class DynamicObject {
private array $data = [];
public function __get(string $name): mixed {
return $this->data[$name] ?? null;
}
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
}
$obj = new DynamicObject();
$obj->title = "Hello";
echo $obj->title; // Hello
Ejemplo de __isset() y __unset():
<?php
class DynamicObject {
private array $data = [];
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
public function __isset(string $name): bool {
return isset($this->data[$name]);
}
public function __unset(string $name): void {
unset($this->data[$name]);
}
}
$obj = new DynamicObject();
$obj->name = "Test";
echo isset($obj->name) ? "exists" : "missing"; // exists
Estos métodos permiten propiedades dinámicas, carga perezosa (lazy loading) y contenedores de datos flexibles, manteniendo al mismo tiempo la estructura orientada a objetos.
Pruébalo tú mismo
<?php
require_once 'Config.php';
// Leer entradas
$settingName1 = trim(fgets(STDIN));
$settingValue = trim(fgets(STDIN));
$settingName2 = trim(fgets(STDIN));
// TODO: Crear una instancia de Config
// TODO: Establecer el primer ajuste al valor dado
// TODO: Imprimir si el primer ajuste existe ("exists" o "missing")
// TODO: Imprimir el valor del primer ajuste
// TODO: Imprimir el recuento actual de ajustes
// TODO: Usar unset() para eliminar el primer ajuste
// TODO: Imprimir si el primer ajuste existe ahora ("exists" o "missing")
// TODO: Imprimir el valor del segundo ajuste (que nunca fue establecido)
?>Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a OOPClases vs ObjetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Resumen - Calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasResumen - Jerarquía de empleados7Encapsulamiento
Público, Protegido, PrivadoModificadores de acceso a fondoGetters y SettersOcultamiento de informaciónPromoción de constructor (8.0)Resumen - Sistema de registros de estudiantes10Conceptos avanzados de POO
Composición vs. HerenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibers (PHP 8.1)Clonación de objetos a fondoGeneradores e Iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Espacios de nombres y Autoloading
Introducción a los espacios de nombresLa palabra clave useEstándar de Autoloading PSR-4Autoloader de ComposerResumen - Proyecto organizado5Interfaces y Contratos
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesInterfaz vs Clase AbstractaType Hinting con InterfacesResumen - Calculadora de Formas8Métodos mágicos
Introducción a los métodos mágicos__toString y __debugInfo__get, __set, __isset, __unset__call y __callStatic__clone y clonación de objetos__serialize y __unserializeResumen - Colección personalizada3Propiedades de clase
Propiedades de instancia vs. estáticasConstantes en clasesMétodos y propiedades estáticosPropiedades privadas y protegidasPropiedades de solo lectura (PHP 8.1)Resumen - Gestor de cuenta bancaria6Polimorfismo
Sobrescritura de métodos revisadaPolimorfismo mediante interfacesType Hinting y tipos de uniónEnlace estático tardíoResumen - Procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos de TraitsMétodos abstractos en TraitsTraits frente a herencia12Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy