Ankündigung

Einklappen
Keine Ankündigung bisher.

Merkwürdiges Verhalten von Objekten in einem Array

Einklappen

Neue Werbung 2019

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

  • Merkwürdiges Verhalten von Objekten in einem Array

    Ich speichere Child-Objekte mit Daten in einem Array eines Parent-Objektes.
    Soweit alles kein Problem, ich kann dieses Array an eine Funktion übergeben und dieses Array wird dann auch als Kopie erhalten, so das Änderungen nur in der Funktion aber NICHT im Parent Gültigkeit haben.

    Wenn ich aber auch nur einmal eine Methode eines Child's vom Parent aus Aufrufe, ändert sich scheinbar der Inhalt des Array im Parent.
    Weiter Übergaben an Funktionen haben nun zur Folge das sich die Änderungen AUCH auf das Child-Objekt im Parent beziehen.

    Was da nun wirklich passiert kann ich nicht besser beschreiben....

    Beispielcode:
    -------------------------------------------------------------------

    Code:
    //Data-Objekt der Child's
    class child_o {
      var $child_data;
      
      function child_o($child_data) {
        $this->child_data=$child_data;
      }
      //der Name sagt alles
      function nur_mal_eine_child_funktion_zum_aufrufen() {
      }
    }
    
    //Parent-Objekt
    class parent_o {
      var $child_array;
      
      function parent_o() {
        //2 childs als Objekte im Array erstellen und Text zuweisen
        $this->child_array = array();
        $this->child_array[0] = new child_o("Data child 0 is ok");
        $this->child_array[1] = new child_o("Data child 1 is ok");
      }
      
      function fehler_verursachen() {
        //NUR im ersten Objekt eine Funktion aufrufen (eine Funktion ohne Inhalt reicht schon...)
        $this->child_array[0]->nur_mal_eine_child_funktion_zum_aufrufen();
        //und von nun an enthält child_array[0] scheinbar eine Referenz und ist bei normalen nicht referenzierten Funktions-Übergaben änderbar....
      }
      
      function test_funktion_des_ueberschreiben() {
        //eine exteren Funktion aufrufen, diese sollte eigentlich NICHT in der Lage sein Child-Daten dieses Objektes zu ändern (keine Referenzübergabe)!
        externe_function_sollte_daten_nicht_aendern_da_keine_referenz_uebergabe($this->child_array);
      }
    }
    
    function externe_function_sollte_daten_nicht_aendern_da_keine_referenz_uebergabe($object_child_array) {
      //Child-Daten ändern, sollten eigentlich nur in dieser Funktion gültigkeit haben (da keine Referenz)
      foreach ($object_child_array as $key => $value) {
        $object_child_array[$key]->child_data = "warum geändert?";
      }
    }
    
    //Parent erzeugen
    $parent = new parent_o();
    
    //erste Ausgabe, sollte OK sein
    echo "1.: ".$parent->child_array[0]->child_data." / ".$parent->child_array[1]->child_data."
    ";
    
    //erster Versuch die Daten zu ändern (geht aber noch nicht, was auch so sein sollte)
    $parent->test_funktion_des_ueberschreiben();
    // Zweite Ausgabe, sollte auch noch OK sein.
    echo "2.: ".$parent->child_array[0]->child_data." / ".$parent->child_array[1]->child_data."
    ";
    
    //dieser Aufruf verursacht das Problem, denn durch den einfachen Aufruf einer Funktion in Child[0] sind nun die betroffenen Daten des Child[0] wie bei Referenzen änderbar
    $parent->fehler_verursachen();
    //zweiter Versuch die Daten zu ändern, nun werden die Daten des Child[0] geändert - warum auch immer.....
    $parent->test_funktion_des_ueberschreiben();
    // Dritte Ausgabe, nun seht Ihr das Problem
    echo "3.: ".$parent->child_array[0]->child_data." / ".$parent->child_array[1]->child_data."
    ";
    ----------------------------------------------------------------------------
    Das Ausgabe-Ergebniss ist Wundersammerweise:

    1.: child 0 is ok / child 1 is ok
    2.: child 0 is ok / child 1 is ok
    3.: warum geändert? / child 1 is ok

    Wer kann mir das erklären?

    Ach ja, verwendet wird hierbei php 4.3.x (PHP 5 leider nicht z.Z möglich)

    Vielen Dank sagt schon mal der Markus


  • #2
    Hallo Markus,

    schöner Name :wink:

    Vielleicht liegt es an der konsequent falschen Schreibweise von parent, daß der PHP-Interpreter sich weigert, logisch vorzugehen. Mich hat es zumindest sehr vom Problem abgelenkt

    Aber Ernst:
    Bei mir kommt als Ergebnis:
    Zitat von Mein freundlicher PHP-Interpreter
    1.: Data child 0 is ok / Data child 1 is ok
    2.: warum geändert? / warum geändert?
    3.: warum geändert? / warum geändert?
    Und finde es auch eigentlich klar. Ich nehme an, daß Du PHP5 verwendest, da Du auf die Methoden der Objekte des Arrays direkt zugreifst.

    PHP5 speichert freundlicherweisen (fast) immer Referenzen auf Objekte und hier auch in dem Array. Auch wenn Du eine Kopie des Arrays übergibst, So liegt doch die Referenz auf das Objekt im Array. Alles klar?
    Wenn Du mal unter Deinen Testcode schreibst:
    Code:
    echo $parend->child_array[0];
    bekommst Du womöglich sowas zu sehen, und dann ist es wohl klar, daß die Referenz im Array erhalten bleibt:
    Zitat von Mein freundlicher PHP-Interpreter
    Object id #2
    Gruß
    MarkusHausB

    Kommentar


    • #3
      profi?
      Klick mich


      Kommentar


      • #4
        Hallo Markus

        Leider kann ich zur Zeit keine PHP 5 einsetzen und verwende daher php 4.3.x

        Das PHP 5 diese Ergebnis bringt ist schon klar, ist aber auch ähnlich zu PHP 4 wenn ich die Objekte mit & erzeuge a la:

        $this->child_array[0] =& new child_o("Data child 0 is ok");

        wenn möglich, bitte mit < Version 5 testen, ansonsten bring das nicht viel.... (hab ich aber auch vergessen zu erwähnen)

        Aber trotzdem schon mal danke für deine Mühe

        (beim "parend" hat sich der Strg-Teufel eingeschlichen, hab es aber nun geändert, damit das nicht zu sehr ablenkt :wink: )

        Kommentar


        • #5
          so, bescheuerte kommentare und bescheuerte methodennamen mal weggenommen, sieht dein beispielcode folgendermaßen aus:
          PHP-Code:
          <?PHP
          class {
            var 
          $data;
            function 
          A($data) {
              
          $this->data=$data;
            }
            function 
          childMethod() {}
          }

          class 
          {
            var 
          $c;

            function 
          P() {
              
          $this->= array(new A(0),new A(1));
            }
           
            function 
          createError() {
              
          $this->c[0]->childMethod();
            }
           
            function 
          overwrite() {
                
          ext_func($this -> c);
            }
          }

          function 
          ext_func($arr) {
            foreach (
          $arr as $k=> $v) {
              
          $arr[$k]->data 9;
            }
          }

          /** 
           * @param $p P
          */
          function _doAssert(&$p) {
            return (
          $p -> c[0] -> data == && $p -> c[1] -> data == 1);
          }

          $p = new P();
          var_dump(_doAssert($p));
          $p->overwrite();
          var_dump(_doAssert($p));
          $p->createError();
          $p->overwrite();
          var_dump(_doAssert($p));
          ?>
          das ganze gibt unter php5 true,false,false aus (wie gewünscht - referenzen behalten), unter php4 true,true,false - nicht wie gewünscht.

          Code:
          Content-type: text/html
          X-Powered-By: PHP/4.3.10
          
          bool(true)
          bool(true)
          bool(false)
          würde ich als bug ansehen.

          Kommentar


          • #6
            Erst ein mal Danke für eure Bemühungen, das das ein Bug ist hatte ich schon befürchtet.

            Aber warum muss man alles gleich mit "bescheuert" betiteln? Na ja auch egal....

            Leider hab ich nun schon ca. 5000 Zeilen Code in meinem betroffenen Projekt und darf nun alles überarbeiten um diesen Bug zu berücksichtigen....

            cu Markus

            Kommentar


            • #7
              Zitat von Markus
              Erst ein mal Danke für eure Bemühungen, das das ein Bug ist hatte ich schon befürchtet.

              Aber warum muss man alles gleich mit "bescheuert" betiteln? Na ja auch egal....
              ganz einfach:
              die grundregel für bug-meldungen lautet:
              1. möglichst kurzen
              2. möglichst einfachen code abzuliefern, der auch leicht reproduzierbar ist.

              da du netterweise auch noch darauf verzichtet hast, die [ php ] - tags zu verwenden, ist dein 'bug report' wohl das unleserlichste, was man sich vorstellen könnte.
              schlimmer wäre nur noch, das skript in word zu packen und dann das dokument als *.rar zum download anzubieten.

              für's nächste mal könntest du dir die mühe machen, möglichst kurzen code zu schreiben, der den fehler 'immer noch' aufdeckt.


              Leider hab ich nun schon ca. 5000 Zeilen Code in meinem betroffenen Projekt und darf nun alles überarbeiten um diesen Bug zu berücksichtigen....
              tja, das passiert ... das ganze wär ja eh nicht php5-fest gewesen, und 5000 zeilen lassen sich schon noch überblicken - sofern deine methoden nicht so heißen wie in deinem beispiel und man für einen methodennamen quer scrollen darf.

              Kommentar

              Lädt...
              X