jueves, 10 de mayo de 2007

Guardar propiedades static en $_SESSION (II)

Como contaba en mi anterior entrada al contrario del resto de propiedades de un objeto (almacenado en el array $_SESSION) las static, por pertenecer a la clase y no al objeto, no se recuperan con la llamada a la función session_start(). Exprimiendo un poco el coco llegué a una solución bastante eficiente y poco sangrante.



¿A que me refiero con poco sangrante?

Cuando se está buscando un parche, como en este caso, siempre hay que tragar con unas cuantas líneas de código extra. Lo más importante es que éste resulte localizable y que sea fácil de eliminar llegado el caso. El código que propongo se compone de una clase extra que actuará independientemente, y de dos método "mágicos" en cada clase que tenga propiedades static que deseemos mantener en session. Estos métodos son iguales para todas y son muy simples:

static function __restoreStatics($statics){
foreach($statics as $nombre=>$valor)
self::$$nombre=$valor;
}

static function __getStatics(){
$statics=array();
$reflejo=new ReflectionClass(__CLASS__);
$properties=$reflejo->getProperties();

foreach($properties as $p) if($p->isStatic() &&
$p->getDeclaringClass()->getName()===__CLASS__ ) {

$nombre=$p->getName();
$valor=self::$$nombre;
if(!is_resource($valor)) $statics[$nombre]=$valor;
}
return $statics;
}

¿Por qué son imprescindible estos métodos?

Sólo un método de la propia clase puede acceder las propiedades private y protected (en las primeras versiones, PHP 5 no era tan estricto). Cualquier posible solución tiene que contar con dos métodos definido en aquellas clases con propiedades static que queramos conservar.
Ojo: estos métodos no pueden ser heredados, hay que definirlos para cada clase. Veamos como funcionan:

  1. El método __getStatics apollado en un objeto ReflectionClass obtiene los atributos static de la clase (objetos ReflectionProperty). Comprueba que no se trata ni de un atributo heredado ni de un recurso y devuelve un array asociativo indexado por el nombre de cada atributo.

  2. El método __restoreStatics hace lo contrario, se le pasa el array de statics y vuelve establecer los atributos a los valores dados.


Por lo dicho ya vemos que el método __getStatics debería ser invocado cuando se finalice el script, almacenando el resultado que obtengamos para cada clase. Al contrario, el método __restoreStatics será llamado cuando se inicie la ejecución del script. Si prefieres puedes ver estos dos métodos como dos más de los "métodos mágicos", como __sleep o __wakeup, así no suena tan mal.

Con estos dos métodos ya casi tenemos solucionado todo el problema. En el siguiente post veremos con más detalle la API de Reflexión que parece va adquiriendo importancia en este problema.

Hasta el próximo
Ir a... [I][III][IV]

No hay comentarios: