Indirect modification of overloaded property

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Indirect modification of overloaded property

    Ich habe eine Frage, weshalb diese Fehlermeldung in einem bestimmten Fall auftritt:

    Code:
    [B]Notice:[/B] Indirect modification of overloaded property LoginPopo::$rightgroups has no effect in ...
    Akteure sind folgende:

    PHP-Code:
    <?php
    abstract class PHibernatePopo {
        private 
    $objectChanged null;
        
        public function 
    __get($property) {
            return 
    $this->$property;
        }
        
        public function 
    __set($property,$value) {
            if(
    $this->$property !== $value)
                
    $this->objectChanged time();
            
            
    $this->$property $value;
        }
        
        public function 
    resetChanged() {
            
    $this->objectChanged null;
        }
        
        public function 
    hasChanged() {
            if(
    $this->objectChanged === null)
                return 
    false;
            
            return 
    true;
        }
    }
    ?>
    PHP-Code:
    <?php 
    class RightgroupPopo extends PHibernatePopo {
        protected 
    $ID;
        protected 
    $groupname;
    }
    ?>
    Wenn ich nun eine Property so ändere:
    PHP-Code:
    $rightGrpObj $result[0]->rightgroups[0]->rightgroup;
    $rightGrpObj->groupname 'New Name'
    ist das kein Problem. Wenn ich es aber wie folgt ändere:

    PHP-Code:
    $result[0]->rightgroups[0]->rightgroup->groupname 'New Name'
    Gibt es die oben genannte Fehlermeldung. Weshalb?
    Zuletzt geändert von pascal007; 03.02.2012, 09:45.

  • #2
    Kann dir dazu keine Antwort geben, aber das ist ziemlich böse und unlogisch, was du da machst.

    Properties sollten nicht "magisch" erstellt werden. Definiere Properties immer in der Klasse.

    Außerdem hebelst du die Wirkung von protected komplett aus.

    Du solltest übrigens Properties, die du in der abstrakten Klasse ansprichst, auch in der abstrakten Klasse definieren.

    Sinnvoller:
    PHP-Code:
    abstract class Foo {
        private 
    $properties = array();

        public function 
    __get($param) {
            if (! 
    array_key_exists($param$this->properties)) {
                throw new 
    OutOfBound************ception('Property ' $param ' does not exist.');
            }
            return 
    $this->properties[$param];
        }

        public function 
    __set($param$value) {
            if (! 
    array_key_exists($param$this->properties)) {
                throw new 
    OutOfBound************ception('Property ' $param ' does not exist.');
            }
            
    $this->properties[$param] = $value;
        }

        protected function 
    createProperty($name$value null) {
            
    $this->properties[$name] = $value;
        }
    }

    class 
    Bar extends Foo {
        public function 
    __construct() {
            
    $this->createProperty('groupName');
        }

    Zuletzt geändert von h3ll; 03.02.2012, 09:56.

    Kommentar


    • #3
      Danke für deine Antwort .

      Das einzige was ich eigentlich will, ist, festzustellen ob eine Property in dem Object RightgroupPopo geändert hat.

      Hab aber nicht herausgefunden ob PHP da eine Möglichkeit bieter und diese deshalb selbst implementiert.

      Die Felder in der RightgroupPopo sind deshalb protected weil bei "public" die Magic-Method __set() nicht aufgerufen wird (logischerweise). Aber ich brauche einen Trigger der mir sagt: "Hey da hat eine Property geändert!".

      Vielleicht gibt's da ja nen besseren Weg .

      EDIT: Okay folgendes hat mir geholfen: http://mwop.net/blog/131-Overloading...s-in-PHP-5.2.0

      Zudem habe ich meine abstract class dahingehend geändert, dass nun mit Reflection überprüft wird, ob die Property überhaupt existiert. Somit können nicht einfach neue Properties erzeugt werden .

      Neu sieht die Klasse so aus:

      PHP-Code:
      abstract class PHibernatePopo {
          private 
      $objectChanged;
          private 
      $reflection;
          
          public function 
      __construct() {
              
      $this->objectChanged null;
              
      $this->reflection = new ReflectionObject($this);
          }
          
          public function 
      __get($property) {
              
      $prop self::getProperty($property);
              
      $prop->setAccessibletrue );
              
              return 
      $prop->getValue($this);
          }
          
          public function 
      __set($property,$value) {
              
      $prop self::getProperty($property);
              
      $prop->setAccessibletrue );
              
              if(
      $prop->getValue($this) !== $value)
                  
      $this->objectChanged time();
          
              
      $prop->setValue($this,$value);
          }
          
          public function 
      resetChanged() {
              
      $this->objectChanged null;
          }
          
          public function 
      hasChanged() {
              if(
      $this->objectChanged === null)
                  return 
      false;
              
              return 
      true;
          }
          
          private function 
      getProperty($property) {
              if(
      $this->reflection->hasProperty($property) === false)
                  throw new 
      OutOfBound************ception('Property "' $property '" does not exists in class "' get_class($this) . '"');
              
              return  
      $this->reflection->getProperty($property);
          }

      EDIT 2: Der Fehlermeldung verschwindet auch wenn man "public function __get()" in "public function &__get()" ändert.
      Zuletzt geändert von pascal007; 03.02.2012, 11:57.

      Kommentar


      • #4
        Zitat von pascal007 Beitrag anzeigen
        EDIT 2: Der Fehlermeldung verschwindet auch wenn man "public function __get()" in "public function &__get()" ändert.
        Das hat dann aber mit einer sauberen Programmierung dann überhaupt nichts mehr zu tun. Da kannst du gleich die Fehlermeldungen komplett ausschalten und sie ignorieren.

        Das Ziel sollte nicht sein eine Fehlermeldung zu eliminieren, sondern den tatsächlichen Fehler zu beheben.

        Kommentar


        • #5
          Das heisst die Lösung mit dem ArrayObject wäre sauber(er?)?

          Kommentar


          • #6
            Die Variante mit Reflection geht schon in die richtige Richtung.

            Soll das übrigens ein Hibernate-Nachbau werden? Dann schau dir mal Doctrine ORM an. Das ist nämlich mehr oder weniger ein Hibernate-Klon.
            Zuletzt geändert von h3ll; 03.02.2012, 12:38.

            Kommentar

            Lädt...
            X