Ankündigung

Einklappen
Keine Ankündigung bisher.

klassen variable wird zur referenz und ist von aussen manipulierbar

Einklappen

Neue Werbung 2019

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

  • klassen variable wird zur referenz und ist von aussen manipulierbar

    Hallo,

    Problem: im nachfolgenden code werden die einträge der Klassen-variable $_data zur referenz auf sich selbst. Dadurch sind diese von aussen manipulierbar.

    Allerdings wurde $this->_data nie als referenz definiert, sondern nur keys innerhalb von $this->_token, die auf keys von $this->_data verweisen.

    Ich bin mit meinem Latein am Ende. Ist es ein Bug oder missverstehe ich nur (was ich da tue). Freue mich sehr über ein Feedback und ggf. Hilfestellung!

    getestet mit PHP 5.5.13 und 5.3.10
    Vielen Dank schonmal!

    PHP-Code:
    abstract class bla {
        protected 
    $_data = array();

        abstract protected function 
    _setRef();

        public function 
    __construct() {
            
    $this->_data = array(
                
    'a' => 'b'
            
    );
            
    $this->_setRef();
        }

        public function 
    getData() {
            return 
    $this->_data;
        }
    }

    class 
    blub extends bla {
        protected 
    $_token = array();

        protected function 
    _setRef() {
            foreach (
    $this->_data as $k => $v) {                                                                                                
                
    //auskommentieren der nächsten zeile lässt $this->_data wie erwartet verhalten
                
    $this->_token[$k] =& $this->_data[$k];
            }
        }
    }

    $c = new blub();
    $b $c->getData();

    var_dump($b);
    /*
    result:
    array (size=1)
      'a' => &string 'b' (length=1)
    */
    $b['a'] = 'd';
    var_dump($c->getData());
    /*
    result:
    array (size=1)
      'a' => &string 'd' (length=1)

      but expected:
    array (size=1)
      'a' => &string 'b' (length=1)
    */ 


  • #2
    Tja… Gute Frage.

    Schlechte Antwort: Wird eine Referenz auf ein Array-Element erstellt, dann wird das Array-Element selbst zur Referenz. Wird das Array nun kopiert, dann wird diese Referenz nicht aufgelöst, sondern mitkopiert.

    PHP-Code:
    $a = ['foo'];  // Array mit einem Element erstellen
    $t = &$a[0];   // Referenz erstellen (Element wird zu Referenz)
    $w $a;       // Array "echt" kopieren (Referenz bleibt erhalten)
    $w[0] = 'bar'// Element ändern
    var_dump($t$w[0], $a[0]); // bar, bar, bar 
    I don’t even…

    PHP-Code:
    $a1 = ['foo']; // (genau wie oben)
    $t1 = &$a1[0];
    $w1 $a1;
    $w1[0] = 'bar';
    var_dump($t1$w1[0], $a1[0]); // bar, bar, bar

    $a2 = ['foo'];
    $t2 = &$a2[0];
    $w2 = new ArrayObject($a2);
    $w2[0] = 'bar';
    var_dump($t2$w2[0], $a2[0]); // foo, bar, foo

    $a3 = ['foo'];
    $t3 = &$a3[0];
    $w3 = (new ArrayObject($a3))->getArrayCopy();
    $w3[0] = 'bar';
    var_dump($t3$w3[0], $a3[0]); // bar, bar, bar

    $a4 = ['foo'];
    $t4 = &$a4[0];
    $w4 unserialize(serialize($a4));
    $w4[0] = 'bar';
    var_dump($t4$w4[0], $a4[0]); // foo, bar, foo 
    Gefundenes Zeugs:

    - http://float-middle.blogspot.de/2010...ments-are.html
    - http://stackoverflow.com/questions/8...-of-references

    Ich bin mit meinem Latein am Ende.
    Ich kann es auch nur beschreiben.

    Ein Suchbegriff wäre wahrscheinlich noch: „php array remove references“

    Kommentar


    • #3
      Hallo greenTeeFlavor,

      Ich habe vor einer ganzen Weile genau dasselbe Verhalten einmal beobachten können,
      darum habe Dir mal den Beitrag von damals rausgesucht, vielleicht nützt er Dir irgendwas. ^^

      http://www.php.de/php-fortgeschritte...enzierung.html

      Edit:


      http://www.php.de/php-fortgeschrittene/97874-erledigt-problem-mit-referenzierung.html#post720275

      Kommentar


      • #4
        (Hoffentlich) Bessere Antwort:

        Anschaulicher, einfacher Code zum reproduzieren [ich stelle eben fest, dasselbe wie mermshaus, aber nur nochmals zum erklären]:
        PHP-Code:
        $array = array(1);
        $ref = &$array[0];
        $kopie $array;
        $kopie[0] = 2;
        var_dump($array[0]); // int(2) 
        PHP unterscheidet nicht zwischen referenzierter Variable und Variable der die Referenz zugewiesen wurde.
        Beide Variablen verweisen intern auf einen und denselben Inhalt.
        Und bei normalen Kopien eines Arrays werden Referenzen nicht aufgelöst, sondern einfach mitkopiert: wir haben jetzt einfach drei Variablen ($ref, $kopie[0] und $array[0]), die auf den selben Inhalt verweisen.

        Code:
        $6 = {value = {lval = 1, /* ... */}, refcount__gc = 3, type = 1 '\001', is_ref__gc = 1 '\001'}
        Wird jetzt eine der drei Variablen geändert, so ändern sich alle drei.

        _____


        Um jetzt noch auf mermshaus Beispiele mit ArrayObject einzugehen:

        Bei einer Zuweisung auf ein direktes Element von ArrayObject werden Referenzen nicht berücksichtigt, der Wert wird einfach ersetzt und verliert seinen Referenz-Status.

        PHP-Code:
        (new ArrayObject($a3))->getArrayCopy() 
        gibt eine normale Kopie des Arrays zurück (Referenzen also mitkopiert).

        Und bei Serialisierung wird im serialisierten String keine Information über die Referenz mitgespeichert, folglich enthält das deserialisierte Array auch keine Referenz.

        _____


        Ich hoffe hiermit sollte alles klar sein, bei weiteren Fragen einfach fragen.

        Kommentar

        Lädt...
        X