Kai: Objekt überschreiben

Hallo
Habe eine Frage, die ich am besten direkt mit Quelltext stelle:
-----------------------------------------------------------
class A
{
 static function SetObject(&$Object, $Value) {
  $Test = new B();
  $Test->Value = $Value;
  $Object = $Test;
 }
}

class B
{
 public $Value;

public function Test() {
  A::SetObject($this, -1);
 }
}
$Class1 = new B();

$Class1->Value = 3;
A::SetObject($Class1, 100);
echo $Class1->Value; // Wie erwartet, 100
$Class1->Test();
echo $Class1->Value; // wie befürchtet immer noch 100
-----------------------------------------------------------

Zunächst mal:
Ich weiß, ist ein wenig Abentäuerlich was ich da vor habe, also bitte keine bösen Aufschreie.
Mein eigentliches Problem ist die Statuslosigkeit von HTTP.
Also will ich (am Ende des Scripts) den Status verschiedener Objekte in einer Session speichern, damit ich diese beim nächsten Aufruf widerherstellen und mit den alten Werten weiter arbeiten kann.
Das müsste über eine Backendklasse passieren, daher der Umweg hier über eine 2. Klasse.
Dass mein bisheriges Vorgehen ins Leere führt habe ich bereits befürchtet ($this = .... geht ja schließlich auch nicht).

Gibt es andere Möglichkeiten???

Danke
Kai

  1. Ich grüsse den Cosmos,

    Gibt es andere Möglichkeiten???

    Vermutlich nur ne Session, da der Browser beim nächsten Aufruf dem Script ja sonst wieder unbekannt ist.

    Möge das "Self" mit euch sein

    --
    Fragt ein Atom das andere: Hast du mein Elektron gesehen? Ich bin heute so positiv.
    ie:{ br:> fl:| va:| ls:& fo:{ rl:( n4:{ de:] ss:) ch:? js:| mo:) sh:( zu:)
    1. Vermutlich nur ne Session, da der Browser beim nächsten Aufruf dem Script ja sonst wieder unbekannt ist.

      Ja das war doch mein Reden.
      Das Problem ist aber, die Objekte, die in der Session gespeichert sind, auf die Objekte im Skript zu übertragen (s. exemplarischen Codeschnippsel oben).

      1. Ich grüsse den Cosmos,

        Ja das war doch mein Reden.

        Ich gebs zu, ich hab dein Post nur überflogen, weil ich grad Besuche bekam ~g~

        Das Problem ist aber, die Objekte, die in der Session gespeichert sind, auf die Objekte im Skript zu übertragen (s. exemplarischen Codeschnippsel oben).

        http://de.php.net/manual/de/function.hw-array2objrec.php
        evtl. hilft dir das weiter. Habs aber noch nie benutzt und kann daher nicht sagen obs funktioniert.

        Möge das "Self" mit euch sein

        --
        Fragt ein Atom das andere: Hast du mein Elektron gesehen? Ich bin heute so positiv.
        ie:{ br:> fl:| va:| ls:& fo:{ rl:( n4:{ de:] ss:) ch:? js:| mo:) sh:( zu:)
  2. echo $begrüßung;

    $Class1 = new B();
    $Class1->Value = 3;

    A::SetObject($Class1, 100);
    echo $Class1->Value; // Wie erwartet, 100

    Ja, aber: $Class1 ist nun ein neues Objekt und nicht mehr das, was du vorher mit new B() erzeugt hast. Füge debug_zval_dump($Class1); vor und nach der Zeile A::SetObject... ein. Dann siehst du #1 und #2.

    $Class1->Test();
    echo $Class1->Value; // wie befürchtet immer noch 100

    Innherhalb der Methode Test() hast du ein $this, das eine Referenz auf das aktuelle Objekt (#2) ist. Durch dein SetObject() erreichst du, dass $this nun eine Referenz auf das neue Objekt #3 ist. Doch $Class1 bekommt davon nichts mit, denn das referenziert immer noch auf #2.

    Gespickt mit Testausgaben sieht der Code so aus:

      
    class A {  
      static function SetObject(&$Object, $Value) {  
        echo 'Object-1: '; debug_zval_dump($Object);  
        $Test = new B();  
        $Test->Value = $Value;  
        echo 'Test: '; debug_zval_dump($Test);  
        $Object = $Test;  
        echo 'Object-2: '; debug_zval_dump($Object);  
      }  
    }  
      
    class B {  
      public $Value;  
      
      public function Test() {  
        echo 'this-1: '; debug_zval_dump($this);  
        A::SetObject($this, -1);  
        echo 'this-2: '; debug_zval_dump($this);  
      }  
    }  
      
    $x = $Class1 = new B();  
    $Class1->Value = 3;  
    echo 'Class1-1: '; debug_zval_dump($Class1);  
      
    A::SetObject($Class1, 100);  
    echo $Class1->Value; // Wie erwartet, 100  
    echo 'Class1-2: '; debug_zval_dump($Class1);  
      
    $Class1->Test();  
    echo $Class1->Value; // wie befürchtet immer noch 100  
    echo 'Class1-3: '; debug_zval_dump($Class1);
    

    Nachdem $Class1 durch #2 überschrieben wurde, verweist nichts mehr auf #1. Das Objekt wird aufgeräumt und die Nummer 1 wiederverwendet. Das stört etwas die Nachvollziehbarkeit, weswegen ich mit $x eine Referenz auf #1 erzeugt habe, die #1 leben lässt. Somit bekommen wir #3 und keine zweite #1 in den Ausgaben von debug_zval_dump().

    Also will ich (am Ende des Scripts) den Status verschiedener Objekte in einer Session speichern, damit ich diese beim nächsten Aufruf widerherstellen und mit den alten Werten weiter arbeiten kann.

    Ich denke, du kannst dafür eine Registry einsetzen, die die verschiedenen Objekte an einer zentralen Stelle zusammenfasst. Diese Registry kannst du am Ende der Session übergeben und sie am Anfang aus ihr wiederherstellen. Eine Implementation einer Registry gibt es im Zend Framework.

    Du erstellt deine Objekte wie üblich, arbeitest ganz normal mit ihnen und meldest sie lediglich in der Registry an. Das kann gleich nach der Instantiierung erfolgen. Wenn du keine Kopfstände mit ihnen machst, bei denen dir die Referenzen auf die Objekte verlorengehen, denke ich, ist das eine klare und überschaubare Lösung.

    Zu beachten ist, dass PHP5 generell Referenzen bei Objekten verwendet. Das kann nachteilig sein, wenn das Objekt in der Session sitzt und mit Referenzen darauf an anderen Stellen gearbeitet wird, da ein Zugriff auf eine Session-Variable aufwendiger ist als bei einer normalen Variable. Bei spärlichem Gebrauch fällt dies aber praktisch kaum ins Gewicht. Gegebenenfalls musst du die Registry aus der Session clonen, wobei du sicher Object cloning beachten musst, sonst hast du wegen der "shallow copy" zwar einen clone der Registry, aber weiterhin Referenzen der darin abgelegten Objekte.

    echo "$verabschiedung $name";