miércoles, 25 de junio de 2025

Creación de Proxies Dinámicos con Manipulación de Propiedades en PHP

Creación de Proxies Dinámicos con Manipulación de Propiedades en PHP

En PHP, la metaprogramación puede lograrse a través de varios mecanismos, incluyendo la magia methods. Un patrón particularmente útil es la creación de proxies dinámicos, que permiten interceptar y manipular el acceso a propiedades de objetos. Este post explorará la implementación de un proxy dinámico que intercepte la lectura y escritura de propiedades, permitiendo transformaciones o validaciones personalizadas.


<?php

class DataObject {
    private $data = [];

    public function __construct(array $initialData = []) {
        $this->data = $initialData;
    }

    public function __get(string $name) {
        if (array_key_exists($name, $this->data)) {
            return strtoupper($this->data[$name]); // Ejemplo de manipulación: convertir a mayúsculas
        }
        return null;
    }

    public function __set(string $name, $value) {
        if (is_string($value)) {
            $this->data[$name] = trim($value); // Ejemplo de manipulación: eliminar espacios en blanco
        } else {
            throw new InvalidArgumentException("El valor debe ser una cadena.");
        }
    }

    public function __isset(string $name): bool {
        return isset($this->data[$name]);
    }

    public function __unset(string $name): void {
        unset($this->data[$name]);
    }
}

// Ejemplo de uso:
$data = new DataObject(['nombre' => '  Juan  ', 'edad' => '25']);

echo $data->nombre . "<br>"; // Imprime: JUAN (convertido a mayúsculas)

$data->ciudad = '  Buenos Aires  ';
echo $data->ciudad . "<br>"; // Imprime: BUENOS AIRES (convertido a mayúsculas)

//echo $data->edad; // Produce un error, porque no está permitido asignar un número.
// $data->edad = 30; // Esta línea provocaría una excepción.

var_dump(isset($data->nombre)); // Imprime: bool(true)
unset($data->nombre);
var_dump(isset($data->nombre)); // Imprime: bool(false)
?>
    

El código anterior define una clase DataObject que actúa como un proxy dinámico para acceder y manipular datos. Los métodos mágicos __get, __set, __isset y __unset interceptan las operaciones de lectura, escritura, verificación y eliminación de propiedades, respectivamente. En este ejemplo, __get convierte el valor de la propiedad a mayúsculas antes de retornarlo, y __set elimina los espacios en blanco al inicio y al final de la cadena antes de almacenarla. Además, implementa una validación básica para asegurar que solo se asignen cadenas.


<?php
// Una version alternativa usando ArrayAccess
class DataObjectArrayAccess implements ArrayAccess {
    private $data = [];

    public function __construct(array $initialData = []) {
        $this->data = $initialData;
    }

    public function offsetSet($offset, $value): void {
        if (is_null($offset)) {
            $this->data[] = $value;
        } else {
             if (is_string($value)) {
                $this->data[$offset] = trim($value); // Ejemplo de manipulación: eliminar espacios en blanco
            } else {
                throw new InvalidArgumentException("El valor debe ser una cadena.");
            }
        }
    }

    public function offsetExists($offset): bool {
        return isset($this->data[$offset]);
    }

    public function offsetUnset($offset): void {
        unset($this->data[$offset]);
    }

    public function offsetGet($offset): mixed {
        if (array_key_exists($offset, $this->data)) {
            return strtoupper($this->data[$offset]); // Ejemplo de manipulación: convertir a mayúsculas
        }
        return null;
    }
}

// Ejemplo de uso:
$dataArray = new DataObjectArrayAccess(['nombre' => '  Juan  ', 'edad' => '25']);
echo $dataArray['nombre']. "<br>";
$dataArray['ciudad'] = '  Buenos Aires  ';
echo $dataArray['ciudad']. "<br>";

var_dump(isset($dataArray['nombre']));
unset($dataArray['nombre']);
var_dump(isset($dataArray['nombre']));

?>
    

Este segundo ejemplo usa la interfaz ArrayAccess de PHP. Permite acceder al objeto utilizando notación de array ($objeto['propiedad']) en lugar de la notación de objeto ($objeto->propiedad). Los métodos offsetSet, offsetExists, offsetUnset, y offsetGet corresponden a __set, __isset, __unset y __get respectivamente. El resto de la funcionalidad es similar al primer ejemplo.

En conclusión, los proxies dinámicos ofrecen una forma poderosa de controlar y personalizar el acceso a propiedades de objetos en PHP. Permiten implementar lógica de validación, transformación y manipulación de datos de manera centralizada, mejorando la mantenibilidad y flexibilidad del código.

No hay comentarios:

Publicar un comentario