Klasse Klasse! (Class in Session)

ZodiacXP

Erfahrenes Mitglied
Währe es nicht klasse wenn eine Klasse in einer Session gespeichert ist?
Ja, das geht ganz einfach über serialize() (http://www.php-faq.de/q/q-sessions-objekte.html)

Aber leider nur außerhalb des Objekts oder vertue ich mich da?

Würde das ganze gerne im Konstrukt unterbringen, damit das jede Klasse selbstständig macht. Ungefähr so:
PHP:
function __construct()
{
  if (get_class($_SESSION["class"]["Userinformation"]) != "Userinformation")
  {
    $_SESSION["class"]["Userinformation"] = &$this;
  }
  else
  {
    $this = &$_SESSION["class"]["Userinformation"];
  }
}

Natürlich ist das in der Art unmöglich.
 
Das verwirrt mich... Warum willst du das machen?
Finde gerade im Kopf kein Sinnvolles Beispiel.

Der erste Teil ist ja noch okay - aber du kannst $this nicht plötzlich eine andere Referenz geben.

Wozu willst du das benutzen wenn man fragen darf?

Ich halte es auch nicht für sonderlich schlau Referenzen in Session-Variablen zu speichern. Diese würden ja auch nach Scriptablauf
bestehen bleiben - allerdings wird das objekt beim nächsten Scriptablauf sicher nicht nochmal die selbe Adresse bekommen. Das
führt unnötig zu Problemen.

lg
 
Ok. Das die nich die selbe Adresse erhalten stimmt. Also ohne Referenz.
Dann einfach innerhalb der Klasse das Objekt irgendwie in die Session bringen.

Der Sinn dahinter ist, die ganzen Werte der Instanzvariablen u.ä. wieder aus der Session zu holen, damit zum einen der Quellcode der Seite (wo das Objekt genutzt wird) übersichtlicher und kürzer ist und einmal aufwendig berechnete Werte nicht bei jedem Seitenaufruf wieder zu berechnen... Nenn' es Cache vom Object oder whatever ^ ^
Fand es halt eine nette Idee, sowas in der Klasse abzuwickeln, vor allem wenn andere, die sich nicht so damit auskennen, die Klasse auch nutzen.
 
Ich muss leider gerade feststellen das sich PHP anders verhält als erwartet.
Durch das Speichern der Referenz in der Session scheint der Speicher nicht
freigegeben zu werden und das Objekt bleibt bestehen.

Beispiel:

Ausführung1:
PHP:
<?
session_start();

class Testklasse1 {
	
	private $test;
	
	public function __construct($string) {
		if (!isset($_SESSION['class'][__CLASS__]) || get_class($_SESSION['class'][__CLASS__]) == __CLASS__) {
			$_SESSION['class'][__CLASS__] = $this;
		}
		
		$this->test = $string;
	}

}

class Testklasse2 {
	
	private $test;
	
	public function __construct($string) {
		if (!isset($_SESSION['class'][__CLASS__]) || get_class($_SESSION['class'][__CLASS__]) == __CLASS__) {
			$_SESSION['class'][__CLASS__] = $this;
		}
		
		$this->test = $string;
	}

}


$test = new Testklasse1("test12");

echo '<pre>';
print_r($_SESSION['class']);
echo '</pre>';

?>

Ergebnis:
Code:
Array
(
    [Testklasse1] => Testklasse1 Object
        (
            [test:private] => test12
        )

)

Jetzt das erstaunliche bei Ausführung 2 (diesmal wird ein Objekt aus der anderen Klasse erstellt):
PHP:
<?
session_start();

class Testklasse1 {
	
	private $test;
	
	public function __construct($string) {
		if (!isset($_SESSION['class'][__CLASS__]) || get_class($_SESSION['class'][__CLASS__]) == __CLASS__) {
			$_SESSION['class'][__CLASS__] = $this;
		}
		
		$this->test = $string;
	}

}

class Testklasse2 {
	
	private $test;
	
	public function __construct($string) {
		if (!isset($_SESSION['class'][__CLASS__]) || get_class($_SESSION['class'][__CLASS__]) == __CLASS__) {
			$_SESSION['class'][__CLASS__] = $this;
		}
		
		$this->test = $string;
	}

}


$test = new Testklasse2("Und ein zweiter Scriptdurchlauf");

echo '<pre>';
print_r($_SESSION['class']);
echo '</pre>';

?>

Verblüffendes Ergebnis:
Code:
Array
(
    [Testklasse1] => Testklasse1 Object
        (
            [test:private] => test12
        )

    [Testklasse2] => Testklasse2 Object
        (
            [test:private] => Und ein zweiter Scriptdurchlauf
        )

)

Das Objekt des ersten Aufrufs scheint im Speicher noch irgendwo zu verweilen.
Woher will denn der Server wissen wann er das Objekt vernichten muss?

Schwer zu sagen... Ich würde damit vorsichtig umgehen!

Vllt äußert sich ja jemand dazu :)

lg
 
Hehe. Hab grad auch eine abstrakte geschrieben und mich erstmal gefragt warum ich get_class() verwende wo es doch __CLASS__ gibt :D

Hier eine gekürzte Fassung:

PHP:
abstract class ClassCache {

  /**
   * Store class in Session
   *
   */
  protected final function init($sClassName)
  {
    $aClassVar = array_keys(get_class_vars($sClassName));
    foreach ($aClassVar as $s)
    {
      if (isset($_SESSION["class"][$sClassName][$s]))
      {
        $this->{$s} = $_SESSION["class"][$sClassName][$s];
      }
      $_SESSION["class"][$sClassName][$s] = &$this->{$s};
    }
  }
}

Problem : Wie komm ich an alle Instanzvariablen ? ?
get_class_vars() gibt nur die public vars

Das kommt zum "extends" und der __constructor der anderen Klasse ruft stumpf self::init(__CLASS__); auf. Bin mir grad nur unsicher mit dem $this->{$variable} ob das klappt. mal ne runde testen.

Ahja, und btw: Klar das beim nächsten Aufruf das Objekt wieder auftaucht. Is doch in der Session. Das verschwindet nur wenn PHP die zugehörige Klasse nicht kennt oder es auf normalen Weg zerstört wird.
 
Zuletzt bearbeitet:
Mensch da könnte man ja richtig Speicherfressende Konstrukte basteln. So zum beispiel würden alle Objekte dieser Klasse in einer Art Historie gespeichert:
PHP:
class Testklasse {
	
	private $beschreibung;
	
	public function __construct($string) {
		$newid = count($_SESSION['class'][__CLASS__]);
		if (!isset($_SESSION['class'][__CLASS__][$newid]) || get_class($_SESSION['class'][__CLASS__][$newid]) == __CLASS__) {
			$_SESSION['class'][__CLASS__][$newid] = $this;
		}
		
		$this->beschreibung = $string;
	}
	
}

Zurück zum Problem:
Kann es sein das du so eine Art Singleton anstrebst?

PHP:
<?
session_start();

final class Testklasse {
	
	private $beschreibung;
	
	private function __construct($string) {
		$this->beschreibung = $string;
	}
	
	public static function getInstance($beschreibung) {
		if (!isset($_SESSION['class'][__CLASS__])) {
			$_SESSION['class'][__CLASS__] = new Testklasse($beschreibung);
		}
		return $_SESSION['class'][__CLASS__];
	}
	
	public function getBeschreibung() {
		return $this->beschreibung;
	}
	
}

$test = Testklasse::getInstance("erster");
echo $test->getBeschreibung();

echo '<pre>';
print_r($_SESSION['class']);
echo '</pre>';

?>

So könnte von Testklasse nur genau ein Objekt erstellt werden.
Allerdings nicht sehr konsequent und es kommt leicht zu Fehlern da auf die Superglobalen ja von überall zugegriffen werden kann und so jeder an deiner Referenz rumspielen kann.

Meinst du sowas?
Scriptübergreifend pro Benutzer nur ein Objekt einer Klasse erstellen?

lg
 
Nein Singletone war nicht mein bestreben.
Ist wirklich so, dass das Objekt in die Session kommt (zumindest die Variablen) und beim nächsten erstellen des Objekts die Variablen wiederhergestellt werden.

Der Singletone ist im Moment nur ein Nebeneffekt.

EDIT: Jetz sag mir bitte nicht das genau das serialize() macht und serialize innerhalb der Klasse möglich ist. Dann schmeiß ich das Buch hier weg.
session_register würd ja schon reichen, wenn ich wüsste wie man aus der Klasse heraus herausfindet wie das Objekt heißt ( $..... ).
 
Zuletzt bearbeitet:
Es könnte natürlich sein das implizit durch die Zuweisung einer Superglobalen serialize aufgerufen wird - aber das glaube ich nicht. Ich glaube es wird einfach nur die Referenz gespeichert und der GarbageCollector (oder wie das Teil bei PHP heißt) erkennt das diese Referenz auch nach Scriptablauf noch vergeben ist und den Speicher nicht freigibt.

Bisher hast du doch auch kein serialize verwendet...
Was genau ist denn nun dein Bestreben?

lg
 
Kurz gesagt: Das das Objekt sich während einer Session selbst am leben erhält.

Man selbst schreibt nur:
PHP:
$obj = new Foo();

oder

PHP:
if (!$obj) $obj = new Foo();

und den Rest geschieht in der klasse.
 
Man müsste nur mal austesten ob wirklich alles funktioniert.
Also ob auch mySQL-Verbindungen aufrecht erhalten werden usw.

Allerdings glaube ich nicht das es soviele Vorteile mit sich bringt.
Immerhin hast du bei einer Aktualisierung/Änderungen der Klasse dann evt noch
alte Objekte bei Benutzern usw.

Könnte sicher zu Problemen führen.

Und mir fällt immernoch kein günstiges Beispiel ein :)
Höchstens für Benutzerstatistiken. Also wie oft ein
User klickt, in welche Bereiche usw. Das könnte man
damit ja prima realisieren!

Man müsste auchnoch prüfen ob bei einem session_destroy
ganz normal der Destruktor ausgefürt wird. Falls das der Fall
ist würde ich evt auch eine solche Klasse für oben genannte
Zwecke schreiben ;)

lg und gn8
 
Zurück