Foros del Web » Programando para Internet » PHP » Frameworks y PHP orientado a objetos »

Migracion hacia __set() y __get()

Estas en el tema de Migracion hacia __set() y __get() en el foro de Frameworks y PHP orientado a objetos en Foros del Web. Hola! Tengo un problema... una clase que usaba setters y getters "tradicionales" y ahora la estoy pasando a los metodos magicos correspondientes. ¿ el problema ...
  #1 (permalink)  
Antiguo 15/08/2009, 18:45
 
Fecha de Ingreso: agosto-2009
Mensajes: 247
Antigüedad: 15 años, 5 meses
Puntos: 10
Exclamación

Hola!

Tengo un problema... una clase que usaba setters y getters "tradicionales" y ahora la estoy pasando a los metodos magicos correspondientes.

¿ el problema ? me ha cambiado la sintaxis... y ahora debo editar muchisimos archivos. Estoy bien ? o bien confundido?

Antes:
$video->setColor1('888888');

Ahora:
$video->color1 = '888888';

Es asi?
No es que la idea subyacente en POO es abstraerse de la implementacion ?

En esta clase "hija" (extendida) no logro poder ver los atributos de la clase padre!

Código PHP:
<?
class youtube extends video {  #clase hija: youtube  
 // url = source
    
  
function __construct($source=""){       
    
parent::__set('source',$source);
    
parent::setDefault();
    
parent::__set('brand','youtube');    
  }
  
  public function 
__set($var,$val){
    if (
$var=='id'){ // sobre-escribo el metodo "setId"
      
parent::__set('id',$id); 
      
parent::__set('source'," www  .youtube . com/v/$val");
    }
  }
  
  public function 
__get($var){
    return 
parent::__get($var);
  }
  
  function 
__toString (){ 
    return (
parent::__toString());
  }   

 
}  
# fin de clase 
?>


Cuando intento acceder a un atributo definido en un vector en la clase padre.... (ej: keywords)

Cita:
Fatal error: Call to undefined method youtube::keywords()
Ah! la clase padre ("video") comienza asi:

Código PHP:
<?
class video{
  protected 
$vector
  
  public function 
__set($var$val){
    
$this->vector[$var]=$val;
  }
  public function 
__get($var){    
    if(isset(
$this->vector[$var])){
      return 
$this->vector[$var];
    }else{
      return 
NULL;
    }      
  }
...
?>

Última edición por GatorV; 17/08/2009 a las 09:12
  #2 (permalink)  
Antiguo 16/08/2009, 18:49
Avatar de Seppo  
Fecha de Ingreso: marzo-2005
Ubicación: Buenos Aires, Argentina
Mensajes: 1.284
Antigüedad: 19 años, 9 meses
Puntos: 17
Respuesta: Migracion hacia __set() y __get()

Si te pone undefined method es porque estás haciendo $obj->keywords(), deberías hacer $obj->keywords para acceder al getter... Si querés que sea un método, deberías implementar el método mágico __call
  #3 (permalink)  
Antiguo 16/08/2009, 23:43
 
Fecha de Ingreso: agosto-2009
Mensajes: 247
Antigüedad: 15 años, 5 meses
Puntos: 10
Respuesta: Migracion hacia __set() y __get()

Seppo: que tal? podrias darme un ejemplo de como puedo implementar esto ? quisiera que fuera una solucion general para todos los atributos que quiero leer

gracias desde ya por la pista
  #4 (permalink)  
Antiguo 17/08/2009, 09:16
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años, 7 meses
Puntos: 2135
Respuesta: Migracion hacia __set() y __get()

Un ejemplo:
Código PHP:
Ver original
  1. class Foo {
  2.       private $_attributes = array();
  3.  
  4.       public function __construct() {}
  5.  
  6.       public function __set($sVariable, $sData) {
  7.               $this->_attributes[$sVariable] = $sData;
  8.       }
  9.  
  10.       public function __get($sVariable) {
  11.               return $this->_attributes[$sVariable];
  12.       }
  13.  
  14.       public function dumpAttributes() {
  15.               var_dump($this->_attributes);
  16.       }
  17. }
  18.  
  19. $bar = new Foo();
  20. $bar->foo = "baz";
  21. $bar->baz = "foo";
  22. $bar->anumber = 1;
  23.  
  24. $bar->dumpAttributes();

Saludos.
  #5 (permalink)  
Antiguo 17/08/2009, 09:40
 
Fecha de Ingreso: agosto-2009
Mensajes: 247
Antigüedad: 15 años, 5 meses
Puntos: 10
Respuesta: Migracion hacia __set() y __get()

mil gracias GatorV pero en mi caso tengo diriamos una clase hija 'Bar' y el problema lo tengo al intentar acceder la los atributos implementados en $_attributes en la clase padre.

Ahi es que me falla y no me devuelve nada:

Código PHP:
class Bar extends Foo {

  public function 
__get($var){ 
      return 
parent::__get($var); 
    } 


Es lo mismo ? eso parece funcionar......aunque me quedan dudas.... porque por ejemplo no encuentro la forma de "settear" en la clase hija:

Código ejemplo:
Ver original
  1. <?
  2. class Foo {
  3.       protected $_attributes = array();
  4.  
  5.       public function __construct() {}
  6.  
  7.       public function __set($sVariable, $sData) {
  8.               $this->_attributes[$sVariable] = $sData;
  9.       }
  10.  
  11.       public function __get($sVariable) {
  12.               return $this->_attributes[$sVariable];
  13.       }
  14.  
  15.       public function dumpAttributes() {
  16.           echo '<pre>';
  17.               var_dump($this->_attributes);
  18.           echo '</pre>';             
  19.       }
  20. }
  21.  
  22. class Bar extends Foo {
  23.  
  24.   function __construct(){
  25.     $this->_attributes['foo']='otra cosa';
  26.   }
  27.  
  28.   public function __get($var){  
  29.       return parent::__get($var);  
  30.     }  
  31.  
  32. }
  33.  
  34. $bar = new Bar();
  35. $bar->foo = "baz";
  36. $bar->baz = "foo";
  37. $bar->anumber = 1;
  38.  
  39. $bar->dumpAttributes();
  40. ?>

Esto no cambia 'foo' en el array

Última edición por bigwhite; 17/08/2009 a las 09:53
  #6 (permalink)  
Antiguo 17/08/2009, 09:44
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años, 7 meses
Puntos: 2135
Respuesta: Migracion hacia __set() y __get()

Define los atributos como protected, si usas private solo son visibles para esa clase, si lo quieres leer en la clase heredada debes de usar protected.

Te recomiendo que leas sobre la visibiladad en la POO.

Saludos.
  #7 (permalink)  
Antiguo 17/08/2009, 10:08
 
Fecha de Ingreso: agosto-2009
Mensajes: 247
Antigüedad: 15 años, 5 meses
Puntos: 10
Pregunta Respuesta: Migracion hacia __set() y __get()

Cita:
Iniciado por GatorV Ver Mensaje
Define los atributos como protected, si usas private solo son visibles para esa clase, si lo quieres leer en la clase heredada debes de usar protected.

Te recomiendo que leas sobre la visibiladad en la POO.

Saludos.
Te agradezco PERO... no fue justo lo que hice ?
  #8 (permalink)  
Antiguo 17/08/2009, 10:56
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años, 7 meses
Puntos: 2135
Respuesta: Migracion hacia __set() y __get()

Que versión de PHP manejas, el código que editaste (después de mi respuesta) me funciona tal cual, la salida es la esperada:
Código:
array(3) {
  ["foo"]=>
  string(3) "baz"
  ["baz"]=>
  string(3) "foo"
  ["anumber"]=>
  int(1)
}
Saludos.
  #9 (permalink)  
Antiguo 17/08/2009, 11:01
 
Fecha de Ingreso: agosto-2009
Mensajes: 247
Antigüedad: 15 años, 5 meses
Puntos: 10
Respuesta: Migracion hacia __set() y __get()

Hola GatorV!, yo esperaba otra cosa porque en el constructor de la clase hija Bar hice:

$this->_attributes['foo']='otra cosa';

uso PHP5

Cita:
el código que editaste (después de mi respuesta)
No recuerdo haber hecho eso... pero estoy sin dormir.....todo puede ser (al menos no el 'protected')
  #10 (permalink)  
Antiguo 17/08/2009, 11:30
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 17 años
Puntos: 845
Respuesta: Migracion hacia __set() y __get()

el problema es que estas redefiniendo la propiedad foo,
despues del new tenes $bar->foo = "baz";
  #11 (permalink)  
Antiguo 17/08/2009, 12:04
 
Fecha de Ingreso: agosto-2009
Mensajes: 247
Antigüedad: 15 años, 5 meses
Puntos: 10
Respuesta: Migracion hacia __set() y __get()

Cita:
Iniciado por masterpuppet Ver Mensaje
el problema es que estas redefiniendo la propiedad foo,
despues del new tenes $bar->foo = "baz";
MUY cierto! gracias! ahora me queda ver porque no me funciona la clase de videos
gracias a todos!
  #12 (permalink)  
Antiguo 24/08/2009, 22:54
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 19 años, 7 meses
Puntos: 32
Respuesta: Migracion hacia __set() y __get()

Que tal Bigwhite,

Amén que ya tienes el problema resuelto, te sugiero que si no estás haciendo algo raro como un generador de código o similar, evites todo lo que puedas el uso de los get y set mágicos de PHP, que lo único que hacen en la mayoría de los casos es crear un efecto de "atributos públicos" y estos están prohibidos conceptualmente desde los inicios de la POO.

Tu clase no debería exponer sus atributos, a lo sumo hacer un get cuando no te quede otra alternativa y en muy contados casos un set, y siempre que puedas, evita hacer a la vez set / get.

Saludos
__________________
Blog phpsenior.com Cursos a Distancia surforce.com
  #13 (permalink)  
Antiguo 25/08/2009, 05:20
 
Fecha de Ingreso: agosto-2009
Mensajes: 247
Antigüedad: 15 años, 5 meses
Puntos: 10
Respuesta: Migracion hacia __set() y __get()

Cita:
Que tal Bigwhite,

Amén que ya tienes el problema resuelto, te sugiero que si no estás haciendo algo raro como un generador de código o similar, evites todo lo que puedas el uso de los get y set mágicos de PHP, que lo único que hacen en la mayoría de los casos es crear un efecto de "atributos públicos" y estos están prohibidos conceptualmente desde los inicios de la POO.
Que tal.... Enrique? si.... me parecia eso......y me llamaba mucho la atencion

Gracias por tus conceptos
abrazo
  #14 (permalink)  
Antiguo 25/08/2009, 09:41
Avatar de Webstudio
Colaborador
 
Fecha de Ingreso: noviembre-2001
Ubicación: 127.0.0.1
Mensajes: 3.499
Antigüedad: 23 años, 1 mes
Puntos: 69
Respuesta: Migracion hacia __set() y __get()

Igualmente, si bien es sano dejar de lado __set y __get, siempre podés hacer uso del método __call, en el cual podés establecer una implementación de setters y getters que incluso tenga control de scope. No debería ser muy dificil hacer algo asi :

Código PHP:
Ver original
  1. <?php
  2. class A {
  3.     protected $_attributes = array('nombre', 'apellido', 'edad');
  4.     protected $_data = array();
  5.    
  6.     function __call($name, $argument)
  7.     {
  8.         $type = strtolower(substr($name, 0, 3));
  9.         $att_name = strtolower(substr($name, 3));
  10.        
  11.         switch($type)
  12.         {
  13.             case 'get':
  14.                 if(in_array($att_name, $this->_attributes))
  15.                 {
  16.                     return $this->_data[$att_name];
  17.                 }
  18.                 throw new Exception('Atributo no existe, DANGER !!');
  19.             break;
  20.            
  21.             case 'set':
  22.                 if(in_array($att_name, $this->_attributes))
  23.                 {
  24.                     $this->_data[$att_name] = $argument[0];
  25.                     return $argument[0];
  26.                 }
  27.                 throw new Exception('Atributo no existe, DANGER !!');
  28.             break;
  29.            
  30.             default:
  31.                 throw new Exception('llamaste algo que no existe macho, media pila.');
  32.             break;
  33.         }
  34.     }
  35. }
  36. try {
  37.     $a = new A;
  38.     $a->setApellido('pablo');
  39. } catch(Exception $e) {
  40.     echo $e->getMessage();
  41. }
  42. ?>
__________________
Tutoriales Photoshop | Web-Studio.com.ar
Artículos PHP | ZonaPHP.com
  #15 (permalink)  
Antiguo 25/08/2009, 10:24
 
Fecha de Ingreso: agosto-2009
Mensajes: 247
Antigüedad: 15 años, 5 meses
Puntos: 10
Respuesta: Migracion hacia __set() y __get()

EXCELENTE webstudio! yo despues de lo que dijo Enrique... habia pensado en algo parecido, tambien con arrays de metodos pero usando esto dentro de los metodos __set y __get

Esa clase A podria ser la clase padre.... de todas las que utilize, verdad ? asi no tendria que andar copiando todo ese codigo........
  #16 (permalink)  
Antiguo 25/08/2009, 10:36
Avatar de Webstudio
Colaborador
 
Fecha de Ingreso: noviembre-2001
Ubicación: 127.0.0.1
Mensajes: 3.499
Antigüedad: 23 años, 1 mes
Puntos: 69
Respuesta: Migracion hacia __set() y __get()

Hay varios caminos que podrías tomar, pero bueno, heredar a A es uno de ellos. Aunque una clase hija (B) tendría que resetear en su constructor el array $_attributes y con eso ya estarías.
__________________
Tutoriales Photoshop | Web-Studio.com.ar
Artículos PHP | ZonaPHP.com
  #17 (permalink)  
Antiguo 26/08/2009, 06:39
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 19 años, 7 meses
Puntos: 32
Claramente eso es "sobreingeniería", un mal endémico en el desarrollo de software.

La herencia no debe aplicarse SOLO en base al "reuso de código", la herencia es una jerarquía donde debe haber una relación de parentesco.

Cuidado con eso, es muy común ver ese error de conceptos.
__________________
Blog phpsenior.com Cursos a Distancia surforce.com

Última edición por jam1138; 26/08/2009 a las 12:07
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 03:01.