Sobes.tech
Middle

¿Qué métodos mágicos existen en PHP y cómo se utilizan?

sobes.tech AI

Respuesta de la IA

Los métodos mágicos en PHP son métodos especiales que comienzan con doble guion bajo (por ejemplo, __construct) y que se llaman automáticamente en ciertas situaciones.

Los métodos mágicos principales y su uso:

  • __construct(): Se llama al crear un objeto de la clase. Se usa para inicializar las propiedades del objeto y realizar acciones iniciales.

    <?php
    class MyClass {
        public function __construct() {
            echo "¡Objeto creado!";
        }
    }
    $obj = new MyClass(); // Mostrará "¡Objeto creado!"
    
  • __destruct(): Se llama al destruir el objeto (por ejemplo, cuando el script termina o el objeto se elimina de la memoria). Se usa para liberar recursos (cerrar archivos, conexiones a bases de datos).

    <?php
    class MyClass {
        public function __destruct() {
            echo "¡Objeto destruido!";
        }
    }
    $obj = new MyClass();
    unset($obj); // Mostrará "¡Objeto destruido!"
    
  • __call(string $name, array $arguments): Se llama al intentar invocar un método no accesible o inexistente en el contexto del objeto. $name contiene el nombre del método, y $arguments es un array de argumentos.

    <?php
    class MyClass {
        public function __call($name, $arguments) {
            echo "Método '{$name}' no accesible llamado con argumentos: " . implode(', ', $arguments);
        }
    }
    $obj = new MyClass();
    $obj->nonExistentMethod('arg1', 'arg2'); // Mostrará "Método 'nonExistentMethod' no accesible llamado con argumentos: arg1, arg2"
    
  • __callStatic(string $name, array $arguments): Se llama al intentar invocar un método estático no accesible o inexistente en el contexto de la clase. Similar a __call, pero para llamadas estáticas.

    <?php
    class MyClass {
        public static function __callStatic($name, $arguments) {
            echo "Método estático '{$name}' no accesible llamado con argumentos: " . implode(', ', $arguments);
        }
    }
    MyClass::nonExistentStaticMethod('static_arg'); // Mostrará "Método estático 'nonExistentStaticMethod' no accesible llamado con argumentos: static_arg"
    
  • __get(string $name): Se llama al intentar obtener el valor de una propiedad no accesible o inexistente en el contexto del objeto. $name contiene el nombre de la propiedad.

    <?php
    class MyClass {
        private $data = ['key' => 'value'];
        public function __get($name) {
            if (array_key_exists($name, $this->data)) {
                return $this->data[$name];
            }
            return null;
        }
    }
    $obj = new MyClass();
    echo $obj->key; // Mostrará "value"
    echo $obj->nonExistentKey; // Mostrará una cadena vacía (dependiendo del valor de retorno null)
    
  • __set(string $name, mixed $value): Se llama al intentar establecer el valor de una propiedad no accesible o inexistente en el contexto del objeto. $name contiene el nombre de la propiedad, y $value es el valor a establecer.

    <?php
    class MyClass {
        private $data = [];
        public function __set($name, $value) {
            $this->data[$name] = $value;
        }
        public function getData() {
            return $this->data;
        }
    }
    $obj = new MyClass();
    $obj->newKey = 'newValue';
    print_r($obj->getData()); // Mostrará Array ( [newKey] => newValue )
    
  • __isset(string $name): Se llama al usar isset() o empty() en una propiedad no accesible o inexistente en el contexto del objeto. Devuelve un valor booleano.

    <?php
    class MyClass {
        private $data = ['present' => 'value'];
        public function __isset($name) {
            return array_key_exists($name, $this->data);
        }
    }
    $obj = new MyClass();
    var_dump(isset($obj->present));     // Mostrará bool(true)
    var_dump(isset($obj->absent));      // Mostrará bool(false)
    
  • __unset(string $name): Se llama al usar unset() en una propiedad no accesible o inexistente en el contexto del objeto.

    <?php
    class MyClass {
        private $data = ['remove_me' => 'value_to_remove'];
        public function __unset($name) {
            if (array_key_exists($name, $this->data)) {
                unset($this->data[$name]);
                echo "Propiedad '{$name}' eliminada.\n";
            }
        }
        public function getData() {
            return $this->data;
        }
    }
    $obj = new MyClass();
    print_r($obj->getData());
    unset($obj->remove_me); // Mostrará "Propiedad 'remove_me' eliminada." y eliminará el elemento de $data
    print_r($obj->getData());
    
  • __sleep(): Se llama antes de serializar el objeto usando serialize(). Debe devolver un array con los nombres de las propiedades que se deben serializar.

    <?php
    class MyClass {
        public $prop1 = 'value1';
        public $prop2 = 'value2';
        public function __sleep() {
            return ['prop1']; // Solo serializa prop1
        }
    }
    $obj = new MyClass();
    $serialized = serialize($obj); // Serializa solo prop1
    echo $serialized; // Mostrará aproximadamente O:7:"MyClass":1:{s:5:"prop1";s:6:"value1";}
    
  • __wakeup(): Se llama después de deserializar el objeto usando unserialize(). Se usa para restaurar conexiones con bases de datos u otras acciones necesarias después de restaurar el objeto.

    <?php
    class MyClass {
        public $prop1;
        public $resource; // Supongamos que es un recurso de conexión
        public function __wakeup() {
            // Restaurar recurso, por ejemplo, una conexión a la base de datos
            $this->resource = fopen('/tmp/my_file.txt', 'w'); // Ejemplo
            echo "¡Objeto despertado y recurso restaurado!\n";
        }
        public function __sleep() {
            // En __sleep no serializamos el recurso
            return ['prop1'];
        }
        public function __destruct() {
            if (is_resource($this->resource)) {
                fclose($this->resource);
                echo "Recurso cerrado.\n";
            }
        }
    }
    $obj = new MyClass();
    $obj->prop1 = 'valor deserializado';
    $serialized = serialize($obj);
    unset($obj);
    
    $deserialized_obj = unserialize($serialized); // Llamará a __wakeup()
    var_dump($deserialized_obj->prop1);
    
  • __toString(): Se llama cuando el objeto se usa como cadena (por ejemplo, con echo o concatenación). Debe devolver una representación en cadena del objeto.

    <?php
    class MyClass {
        public $name = "MyObject";
        public function __toString() {
            return "Objeto de tipo MyClass con nombre: " . $this->name;
        }
    }
    $obj = new MyClass();
    echo $obj; // Mostrará "Objeto de tipo MyClass con nombre: MyObject"
    
  • __invoke(...): Se llama al intentar invocar el objeto como función. Puede aceptar cualquier cantidad de argumentos.

    <?php
    class MyCallableClass {
        public function __invoke(...$args) {
            echo "El objeto fue llamado como función con argumentos: " . implode(', ', $args);
        }
    }
    $obj = new MyCallableClass();
    $obj('arg1', 123); // Mostrará "El objeto fue llamado como función con argumentos: arg1, 123"
    
  • __set_state(array $properties): Se llama de forma estática para clases exportadas con var_export(). Recibe un array de propiedades exportadas. Debe crear un nuevo objeto de la clase y devolverlo.

    <?php
    class MyClass {
        public $prop;
        public static function __set_state(array $properties) {
            $obj = new MyClass();
            $obj->prop = $properties['prop'];
            return $obj;
        }
    }
    $obj = new MyClass();
    $obj->prop = 'valor exportado';
    $exported = var_export($obj, true); // Exporta el objeto
    // $exported contendrá código para crear el objeto usando __set_state()
    eval('$restored_obj = ' . $exported . ';');
    var_dump($restored_obj); // Mostrará un objeto MyClass con la propiedad 'valor exportado'
    
  • __debugInfo(): Se llama al usar funciones como var_dump() en el objeto. El método debe devolver un array con la información de las propiedades del objeto que se desea mostrar.

    <?php
    class MyClass {
        public $publicProp = 'public';
        private $privateProp = 'private';
        public function __debugInfo() {
            return ['publicProp' => $this->publicProp, 'private_info' => 'algunos detalles sobre privateProp'];
        }
    }
    $obj = new MyClass();
    var_dump($obj); // Mostrará la información devuelta por __debugInfo()
    
  • __clone(): Se llama después de la operación de clonación (clone) del objeto. Se usa para copiar en profundidad objetos internos o estructuras de datos.

    <?php
    class SubObject {
        public $value;
        public function __construct($value) {
            $this->value = $value;
        }
    }
    class MyClass {
        public $object;
        public $anotherProp;
        public function __construct() {
            $this->object = new SubObject('initial');
            $this->anotherProp = 'original';
        }
        public function __clone() {
            // Clonamos el objeto interno para copia profunda
            $this->object = clone $this->object;
        }
    }
    $obj = new MyClass();
    $cloned_obj = clone $obj;
    
    // Ahora $obj->object y $cloned_obj->object son instancias diferentes de SubObject
    $cloned_obj->object->value = 'modificado';
    
    var_dump($obj->object->value);       // Mostrará "initial"
    var_dump($cloned_obj->object->value); // Mostrará "modificado"
    

Tabla con breve descripción:

Método Descripción Se llama cuando...
__construct() Constructor de la clase. Se crea una nueva instancia de la clase.
__destruct() Destructor de la clase. Se elimina el objeto o termina el script.
__call() Maneja llamadas a métodos no existentes o no accesibles del objeto. Se intenta llamar a un método no accesible o inexistente del objeto.
__callStatic() Maneja llamadas a métodos estáticos no existentes o no accesibles. Se intenta llamar a un método estático no accesible o inexistente de la clase.
__get() Maneja la obtención de valores de propiedades no accesibles o inexistentes. Se intenta obtener el valor de una propiedad no accesible o inexistente.
__set() Maneja la asignación de valores a propiedades no accesibles o inexistentes. Se intenta establecer un valor en una propiedad no accesible o inexistente.
__isset() Maneja isset() o empty() en propiedades no accesibles o inexistentes. Se llama a isset() o empty() en una propiedad no accesible o inexistente.
__unset() Maneja unset() en propiedades no accesibles o inexistentes. Se llama a unset() en una propiedad no accesible o inexistente.
__sleep() Preparación para serialización. Se llama a serialize() en el objeto.
__wakeup() Post-procesamiento después de la deserialización. Se llama a unserialize() en el objeto.
__toString() Representación en cadena del objeto. Se usa el objeto como cadena (por ejemplo, con echo).
__invoke() Invoca al objeto como si fuera una función. Se intenta llamar al objeto como si fuera una función.
__set_state() Creación del objeto después de exportarlo con var_export(). Se evalúa código generado por var_export().
__debugInfo() Información para funciones de depuración (var_dump()). Se llama a var_dump() en el objeto.
__clone() Post-procesamiento después de clonar. Se llama a clone en el objeto.