2010-06-23 22 views
0

J'ai créé une courte démonstration du problème que je rencontre. Ce n'est pas exactement comme cela que je le mets en œuvre mais cela semble aboutir au même résultat.Contenus de tableau inattendus en classe utilisant __get, __set et __unset

<?php 

class mainclass { 

    var $vardata = array(); 

    function &__get ($var) { 
     if ($this->vardata[$var]) return $this->vardata[$var]; 
     if ($var == 'foo') return $this->_loadFoo(); 
     return NULL; 
    } 

    function __set ($var, $val) { 
     $this->vardata[$var] = $val; 
    } 

    function __unset($var) { 
     unset($this->vardata[$var]); 
    } 

} 

class extender extends mainclass { 

    function __construct() { 

     var_dump($this->foo); 
     $this->_loadFoo(); 
     echo '<br>'; 
     var_dump($this->foo); 

    } 

    function _loadFoo() { 

     unset($this->foo); 
     $this->foo = array(); 

     $this->foo[] = 'apples'; 
     $this->foo[] = 'oranges'; 
     $this->foo[] = 'pears'; 

     return $this->foo; 

    } 

} 


$test = new extender; 

?> 

La sortie du code ci-dessus est:

array(3) { [0]=> string(6) "apples" [1]=> string(7) "oranges" [2]=> string(5) "pears" } 
array(5) { [0]=> string(6) "apples" [1]=> string(7) "oranges" [2]=> string(5) "pears" [3]=> string(7) "oranges" [4]=> string(5) "pears" } 

Où que je me attendais:

array(3) { [0]=> string(6) "apples" [1]=> string(7) "oranges" [2]=> string(5) "pears" } 
array(3) { [0]=> string(6) "apples" [1]=> string(7) "oranges" [2]=> string(5) "pears" } 

__get, les fonctions de __set et __unset sont tous appelés dans les bons endroits et donc je m'attendais à ce que le deuxième appel direct de la fonction désactive simplement $ this-> foo et le remplisse à nouveau avec les mêmes données. Ce qui signifie que var_dumping donnerait la même sortie. Au lieu de cela, eh bien, il finit par faire ce qui précède ... en le remplissant avec deux des trois cordes directement définies et en gardant les trois premières cordes initiales.

Peut-être juste une erreur idiote ou une incompréhension des fonctions de surcharge - de toute façon, je suis coincé ici depuis trop longtemps maintenant et toute aide est très appréciée!

Répondre

0

Il y avait beaucoup de choses mal avec votre code:

  • if ($this->vardata[$var]) n'est pas le moyen de vérifier est une variable existe; isset ou (si null sont autorisés, array_key_exists) est. Le mainclass a appelé une fonction qu'il n'a pas. Vous auriez dû le déclarer abstrait (cela fonctionnerait toujours autrement, mais vous seriez exposé à des bogues si vous instanciez la mainclass).
  • Vous n'avez pas décidé si vous vouliez _loadFoo définir un élément de tableau manquant (travailler avec des effets collatéraux) ou renvoyer la valeur par défaut de la propriété foo. Puisque vous revenez par référence dans __get, je suppose que vous voulez avoir une variable réelle et pas seulement une valeur de retour, alors je suis allé pour la première route. Vous aviez _loadFoo faire les deux choses - définir l'indice de tableau manquant et renvoyer la valeur; Pour compliquer les choses que vous n'avez pas définies directement dans l'index du tableau, vous avez utilisé des surcharges.

Version corrigée:

<?php 

abstract class mainclass { 

    var $vardata = array(); 

    function &__get ($var) { 
     if (isset($this->vardata[$var])) return $this->vardata[$var]; 
     if ($var == 'foo') { 
      $this->_loadFoo(); /* called for collaterals */ 
      return $this->foo; 
     } 
     return NULL; 
    } 

    abstract function _loadFoo(); 

    function __set ($var, $val) { 
     $this->vardata[$var] = $val; 
    } 

    function __unset($var) { 
     unset($this->vardata[$var]); 
    } 

} 

class extender extends mainclass { 

    function __construct() { 

     var_dump($this->foo); 
     $this->_loadFoo(); 
     echo '<br>'; 
     var_dump($this->foo); 

    } 

    function _loadFoo() { 

     unset($this->foo); 
     $this->foo = array(); 

     $this->foo[] = 'apples'; 
     $this->foo[] = 'oranges'; 
     $this->foo[] = 'pears'; 

    } 

} 

$test = new extender; 
+0

Merci. L'ajout de l'isset le trie dans ma mise en œuvre, un peu un oubli là-bas. D'autres points ont été soulignés sont des points pertinents sur l'échantillon de code que j'ai posté - merci de prendre le temps de regarder à travers. – JoeR