Sitio web no optimizado para IE 6

Cast De Objetos En Php

posteado por Emiliano, categoría Php

24 dic
2009

En este post mostramos como simular el concepto de CAST de objetos en PHP.

Cast o Casting es un concepto de la programación orientada a objetos en que se aplica un operador a una variable para hacer una conversión explicita de tipo de variable.

En el caso de PHP soporta Cast para hacer que una variable de cierto tipo sea convertida a otro tipo de variable, pero manteniendo el valor de la variable. Por ejemplo, podemos convertir un string en un array:

<?php
    $foo = 'Hello World';
    $var = (array) $foo;
    print_r($var); // Debería mostrar array('Hello World')
?>

En el ejemplo anterior, utilizamos el operador "(array)" para convertir la variable de un string a un array. Este es el tipo de cast que nos permite realizar php.

El problema en php es que no permite el cast de objetos, es decir, tener un objeto de cierta clase y convertirlo en un objeto de otra clase, la cual herede de la clase anterior. Por ejemplo, podríamos tener una clase Vehiculo, de la cual extiende otra clase llamada Automovil. Si tenemos un objeto vivo del tipo Vehiculo, y queremos convertirlo en un objeto del tipo Automovil, no podemos hacer lo siguiente:

<?php
    $object = new Vehiculo();
    $newObject = (Automovil) $object; // Esto nos arrojara un Fatal Error.
?>

El ejemplo de arriba nos arrojará un Error Fatal de PHP.

Para poder realizar la conversión entre objetos deseada en el ejemplo de arriba, podemos usar la siguiente función:

<?php
    function cast($old_object, $new_classname){
        if(class_exists($new_classname)){
            $old_serialized_object = serialize($old_object);
            $old_object_name_length = strlen(get_class($old_object));
            $subtring_offset = $old_object_name_length + strlen($old_object_name_length) + 6;
            $new_serialized_object = 'O:' . strlen($new_classname) . ':"' . $new_classname . '":';
            $new_serialized_object .= substr($old_serialized_object, $subtring_offset);
            $new_serialized_object = base64_encode($new_serialized_object);

            return unserialize(base64_decode($new_serialized_object));

        } else {
            return false;
        }
    }
?>

Espero que les sea de utilidad.

Compártelo: technorati Cast De Objetos En Php digg Cast De Objetos En Php facebook Cast De Objetos En Php google Cast De Objetos En Php linkedin Cast De Objetos En Php

9 Comentarios:


jtopo:

11 de Enero de 2010 a las 16:27:39

Hola. Que utilidad tiene aplicar la función bas64_encode? No le veo sentido, ya que inmediatamente le aplicás base64_decode...

hasheado:

11 de Enero de 2010 a las 16:46:27

Hola jtopo, lo de codificar y descodificar es para hacer una serialización y deserialización seguras, ya que de lo contrario los string que se generan al usar serialize, pueden arrojar fatal errors al querer deserializar. Saludos

mauricio:

08 de Febrero de 2010 a las 20:04:36

No seria mejor que cada objeto implement getData y setData con arrays asociativos? extendiendo de la misma claseo o algo? asi lo hago yo.

mauricio:

08 de Febrero de 2010 a las 20:23:48

No entendi lo de los base64, lo busque en internet pero no le veo sentido tampoco. Tal vez si fuera que el texto en base 64 viajara por un form o por un get sería útil por si el base64 se rompiera en el request o algo, pero si lo haces inmediatamente no tiene sentido creo. si no queres que tire errores creo que podes hacer: $new_serialized_object = @serialize($new_serialized_object); return @unserialize($new_serialized_object);

hasheado:

08 de Febrero de 2010 a las 20:41:59

Hola Mauricio, antes q nada gracias por visitar el sitio y comentar, no te entendi bien a que te referis con lo de implementar getData y setData. En cuanto a lo de base64, no es que si no se codifica en base64 el script no funcione, tranquilamente funcionará sin utilizar esa codificación, pero yo la uso asi xq en algún momento use el script sin codificar la serialización y me arrojaba error, el cual se soluciono al usar base64. Un saludo.

mauricio:

08 de Febrero de 2010 a las 21:47:57

Te comento que no es buena practica lo que haces: te adjunto un script que te muestra por que (espero que el editor no me lo corte). por otro lado fijate que aca lo uso sin hacer base64 y funciona perfectamente. class x1{ private $val1 = "x1::val1"; protected $val2 = "x1::val2"; public $val3 = "x1::val3"; private $val4 = "x1::val4"; protected $val5 = "x1::val5"; public function getXVal1(){ return($this->val1); } public function getXVal2(){ return($this->val2); } public function getXVal3(){ return($this->val3); } public function getXVal4(){ return($this->val4); } public function getXVal5(){ return($this->val5); } } class y1 extends x1{ private $val1 = "y1::val1"; public $val2 = "y1::val2"; public $val4 = "y1::val4"; protected $val5 = "x1::val5"; public function getYVal1(){ return($this->val1); } public function getYVal2(){ return($this->val2); } public function getYVal3(){ return($this->val3); } public function getYVal4(){ return($this->val4); } public function getYVal5(){ return($this->val5); } } function Cast($o, $class){ return(unserialize(preg_replace('/O:[0-9]+:"'.get_class($o).'":/', 'O:'.strlen($class).':"'.$class.'":', serialize($o), 1))); } $x = new x1(); $y = Cast($x, 'y1'); var_dump('getYVal1 returns '.$y->getYVal1()); var_dump('getXVal1 returns '.$y->getXVal1()); var_dump('getYVal2 returns '.$y->getYVal2()); var_dump('getXVal2 returns '.$y->getXVal2()); var_dump('getYVal3 returns '.$y->getYVal3()); var_dump('getYVal3 returns '.$y->getXVal3()); var_dump('getYVal4 returns '.$y->getYVal4()); var_dump('getXVal4 returns '.$y->getXVal4()); var_dump('getYVal5 returns '.$y->getYVal5()); var_dump('getXVal5 returns '.$y->getXVal5()); si lo ejecutas podes ver que se hace lio con las variables privadas. Lo que te comentaba del get / set data es esto. Yo uso en mis objetos un array donde meto todos los datos privados y uso las funciones magicas __call para hacer que getAlgo() me llame a la funcion getData('algo') que hace return $this->_misdatos['algo'], y para el set igual . En fin, lo que hago es guardar en un array, entonces puedo llenar los objetos de otras clases con la misma informacion haciendo esto: $x = new UnaClase(); $y = new OtraClase(); $y->setData($x->getData()); el metodo que usas me parece que no esta muy bueno por el hecho de que genera valores extraños y guardas en el objeto variables que no podes acceder, en ese caso si porque yo las derive, pero trata de accederlas sin que deriven. Obviamente si lo usas no lo vas a cambiar ahora, pero no es como para recomendarlo. saludos

hasheado:

09 de Febrero de 2010 a las 01:58:53

Hola Mauricio ahi estuve probando tu script y esta muy bueno, desde ya te agradezco por el aporte. saludos

kernel32:

12 de Marzo de 2010 a las 01:38:37

al final ... es o no buena practica hacer lo que haces ?? saludos diego

hasheado:

12 de Marzo de 2010 a las 01:56:09

@kernel32: el cast de objetos no es soportado por PHP, este script es una manera de simularlo, asi que si es de utilidad y como puedes leer en los comentarios hay otras alternativas también de hacerlo. Saludos.

Comentar este Artículo






Captcha ImageReload_original