Willkommen ~Gast!
Registrieren || Einloggen || Hilfe/FAQ || Staff
Probleme mit der Registrierung im Forum? Melde dich unter registerEin Bild.
Autor Beitrag
000
30.06.2007, 19:56
cleric



Ein wunderschönen guten Abend!

Ich arbeite momentan zum lernen an einem login-System für eine Website.
Als Anfänger scheitere ich da leider schon recht früh.

Mein Problem hängt mit dem speichern eines Objektes in $_SESSION und get_class_vars() zusammen.

Also, ich habe eine Klasse user in der der Username gespeichert wird:

Quellcode:class user
{
private $str_user = 'noName';



public function __construct($name)
{
$this->str_user = $name;
}



public function sayName()
{
echo "Der Benutzer heisst $this->str_user .<br>";
}



public function setName($par_name)
{
$this->str_user = $par_name;
}



public function __sleep()
{
  return array('str_user');
}
}
Nach dem Session-Start wird geprüft ob in der Session bereits ein Objekt user gespeichert wurde.
Falls ja, wird es in $user gespeichert, ansonsten ein neues Objekt angelegt.
Dann folgt der eigendliche Code der Website (hier ersetzt durch das Kommentar).
Unmittelbar bevor die Seite beendet wird, wird $user noch serialisiert und in $_SESSION gespeichert.

Quellcode:session_start();

if(isset($_SESSION['ser_user']))
    {
     $user = unserialize($_SESSION['ser_user']);
    }
else
     $user = new user('Chromosone');



/* Hier wird der gesamte Code der Seite, z.B. auch die drei Testfunktionen (s.u.) eingefügt */




$_SESSION['ser_user'] = serialize($user);
/*  Seitenende  */
Soviel zum Initialisieren der Seite.
$user ist jetzt also gesetzt und enthält entweder 'Chromosone' (wenn es gerade erzeugt wurde) oder den Namen den es hatte, als es in $_SESSION gespeichert wurde.

Testen kann man es ganz einfach:
Quellcode:$user->sayName();

$user->setName('cleric');
$user->sayName();
Wenn der user neu angelegt wurde gibt der erste Aufruf "Der Benutzer heisst Chromosone ." zurück (der Name, der dem constructor übergeben wurde) und der Zweite "Der Benutzer heisst cleric ." da der Name zuvor ja auf 'cleric' gesetzt wurde.
Wenn die Seite mehrmals aufgerufen wird, wird zwei mal "Der Benutzer heisst cleric ." angezeigt - hervorragend, Programm läuft so wie es sollte.

Nun wird die Klasse user aber irgendwann mehr als nur den Namen enthalten, da könnten noch dutzende andere Variablen hinzukommen.
Daher möchte ich die Funktion __sleep() insofern verbessern, dass ich nicht bei jeder neu hinzukommenden Variablen den Namen in das array eingeben muss.
Sie sollte selbst nachgucken, welche Variablen die Klasse enthält.
Dazu gibt es die Funktion get_class_vars().
Daher hab ich die Funktion __sleep auf das hier geändert:

Quellcode:public function __sleep()
{
  return get_class_vars('user');
  /* ehemals stand hier return array('str_user'); */
}
So steht es auch auf php.net ( http://www.php.net/manual/de/function.get-class-vars.php ).
Klappt aber nicht.
Wenn $user in $_SESSION gespeichert wird, wird anstatt des richtigen Benutzernamens ('cleric') der Initialisierungsname gespeichert ('noName').

Wenn ich keinen Initialisierungsnamen angebe (also <? class user{ private $str_user; ... ) gibt get_class_vars('user'); ein leeres array zurück.

Weiss jemand wie das kommt, dass in _sleep() bei "return array('str_user');" der Wert des Objektes serialisiert wird, aber bei "return get_class_vars('user');" der Wert der Klasse serialisiert wird ?

--

Der Optimist glaubt, dass wir in der Besten aller Welten leben.
Der Pessimist fürchtet, dass dies stimmt.

ehemals epidemic.

zum Seitenanfang zum Seitenende Profil || Suche
001
30.06.2007, 20:25
K-Putt



Versuchs mal mit serialize(&$user); am Ende der Session.

Hab jetzt ne weile recherchiert, scheinbar arbeiten die __sleep und __wakeup Methoden nicht mit der Originalen Instanz deiner Klasse, sondern mit einer Kopie.

Zu dem Thema findet man auch auf php.net ein paar Infos.

Es ist allerdings eh unsauber, wenn du pauschal alle Variablen deiner Klasse bei _sleep zurück gibst.
Was, wenn mal eine Variable ausgenommen sein soll?

Am besten erstellst du ein Array alá $userData in deiner Klasse, und gibst dieses bei __sleep zurück.
In das Array wirfst du dann den Namen und die sonstigen Daten des Benutzers, und hast in Zukunft auch nicht mehr Aufwand, wenn neue Eigenschaften hinzukommen.

--

Rambo Engineer @ Drippy's 2fort - finest TFC 1.5 || Bild Upload || The world's most advanced open source database


Dieser Beitrag wurde am 30.06.2007 um 20:25 von K-Putt bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
002
01.07.2007, 12:26
cleric



Guten morgen!

Ich habe jetzt ne ganze Menge durchprobiert und _vermute_ dass serialize() von __sleep ein array in der Form:
Quellcode:array( '1' => 'Variable1', '2' => 'Variable2', '3' => 'Variable3')
erwartet. Mache ich das so (also gebe ich die Variablen per Hand ein, was ich ja eigendlich vermeiden will) funktioniert das Programm einwandfrei.
Also der Variablenname ist hier der WERT des arrays.
serialize() braucht also nur den Namen der zu speichernden Variable, den Wert dazu guckt er selber nach.

Die Funktion get_class_vars() gibt nun aber nicht das oben abgebildete array zurück, sondern nimmt den Variablennamen als Schlüssel und den Variablenwert als Wert im array, also so ein array:
Quellcode:array('Variable1' => 'Hello ', 'Variable2' => 'World', 'Variable3' => '!<br>');
serialize() guckt nun aber nur (vermute ich!) auf den Wert, der Schlüssel ist ihm egal. In dem Objekt findet er aber weder eine Variable 'Hello ', noch eine 'World' geschweige denn eine Variable '!<br>'.
serialize() speichert also gar keine Variable.
unserialze() nimmt, weil er keinen Wert für 'Variable1', 'Variable2' und 'Variable3' findet, einfach den Standartwert von der Deklarierung.

Lösung für mein Problem:

Zitat:
K-Putt postete
Am besten erstellst du ein Array alá $userData in deiner Klasse, und gibst dieses bei __sleep zurück.
In das Array wirfst du dann den Namen und die sonstigen Daten des Benutzers, und hast in Zukunft auch nicht mehr Aufwand, wenn neue Eigenschaften hinzukommen.
Nur dass ich die Variablen nicht selber in das array werfe, sondern das array der Funktion get_class_vars() benutze, von dem ich die Schlüssel nehme und als Werte in das zweite array ummünze.
Dabei kann ich dann sogar noch, wie von dir angesprochen, die ein oder andere Variable rausnehmen (ist aber in meinem Fall nur eine Referenz zu einem mySQLVerbindungs-Objekt).

[edit]
So fertig, so klappt's:
Quellcode:public function __sleep()
{
  $ZuSpeicherndeVariablen;
  $Schluessel = 0;
  $VerkehrtesArray = get_class_vars(get_class($this));
  foreach ($VerkehrtesArray as $Variablenname => $egal)
    {
       ++$Schluessel;
       $ZuSpeicherndeVariablen[$Schluessel] = $Variablenname;
    }
  return $ZuSpeicherndeVariablen;
}

--

Der Optimist glaubt, dass wir in der Besten aller Welten leben.
Der Pessimist fürchtet, dass dies stimmt.

ehemals epidemic.


Dieser Beitrag wurde am 01.07.2007 um 12:37 von cleric bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
003
01.07.2007, 17:54
K-Putt



...um das ganze noch mal sachlich zu beschreiben:

get_class_vars liefert ein assoziatives Array zurück, mit dem serialize scheinbar nicht klarkommt.
Stattdessen wird ein Standard-Array benötigt, dessen Werte ab Index 0 fortlaufend gespeichert sind.

Eigentlich müsste serialize mit beiden Arten klarkommen, weil der Schlüssel doch komplett egal ist, in dem Fall.
Vielleicht nicht direkt ein Bug, aber ein unerwartetes Verhalten.

--

Rambo Engineer @ Drippy's 2fort - finest TFC 1.5 || Bild Upload || The world's most advanced open source database

zum Seitenanfang zum Seitenende Profil || Suche
004
01.07.2007, 17:58
oxff



Mach's doch direkt sauber in Python.

--

mwcollect - mein Projekt | oxlog - mein blog | happyhardcore.com Stream - gute Musik

zum Seitenanfang zum Seitenende Profil || Suche
005
01.07.2007, 18:00
K-Putt



Ja ne ist klar, auf so nen Kommentar hab ich gewartet. Troll dich!

--

Rambo Engineer @ Drippy's 2fort - finest TFC 1.5 || Bild Upload || The world's most advanced open source database

zum Seitenanfang zum Seitenende Profil || Suche
006
01.07.2007, 18:29
hausi



array_values und array_keys machen aus deinem asso-array ein normales.

--

zum Seitenanfang zum Seitenende Profil || Suche