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