Objekte in Sessions speichern

Seit der Version 5 bietet PHP bessere und erweiterte Unterstützung für OOP. Doch anders als in anderen Sprachen wie z.B. Java, werden die Objekte bei PHP 5 bei jedem Request neu erzeugt. So ist OO nicht ganz so schön umzusetzen, z.B. ein Benutzer-Objekt während der gesamten Session zu verwenden.

Doch PHP bietet die Möglichkeit, Objekte in der Session zu speichern und so bei einem neuen Request auf ein bereits existierendes Objekt zuzugreifen. Es gibt nur einen kleinen Trick, den man beachten muss: Die Datei(en) mit der Klassen-Definition muss vor dem Start der Session included werden.

//  Zuerst die Datei laden, die die Klasse enthaelt
include_once 'Benutzer.class.php';
//  Dann de Session starten
session_start();
//  Jetzt kann das Objekt aus der Session geladen werden
$Benutzer = $_SESSION['BenutzerObjekt'];

Wird diese Reihenfolge nicht eingehalten, gehen die Daten in dem Objekt beim Speichern in die Session verloren, das Objekt wird also unbrauchbar.

strauberry hat 3 Beiträge geschrieben

20 Kommentare zu “Objekte in Sessions speichern

  1. kb sagt:

    Ja und wie ist das jetzt mit der Performance? 😉
    Ist es schneller einen etwas volleren Arbeitsspeicher zu haben oder jedes mal ein wenig CPU-Zeit mehr zu benutzen?

  2. tcomic sagt:

    Hey super!
    Vielen Dank, genau das wollte ich vor kurzem mal wissen ob das geht und jetzt wirds mir hier auf dem Servierteller präsentiert!

  3. admin sagt:

    @kb: Dieser Beitrag ist mal nicht über Performance. Muss ja auch nicht alles darüber sein, denn manchmal gehts auch einfach um Programmierkomfort oder Lösungen für die Praxis.
    Oder muss ich erst noch so nen tollen Web 2.0-Button mit der Aufschrift „50% Performance-Beiträge“ bauen 😉 ?

  4. strauberry sagt:

    @kb: ich habs jetzt nicht getestet, aber ich denke schon, dass es mit Objekten in Sessions schneller ist, da man seinen Code ganz anderes aufbauen kann… Es wird also nicht nur Rechenzeit beim Erstellen der Objekte gespart, sondern auch beim ganzen restlichen Code, weil einfach die Struktur besser sein kann.

  5. Allerdings sollte man sich gerade im Clusterbetrieb ein paar Gedanken bezüglich der Performance machen.
    In diesem Fall bietet sich gerade für grössere Objekte memcache an. Mit memcache kann man die Objekte bzw die koplette Session im Arbeitsspeicher ablegen.
    Gerade in Hinsicht auf race conditions sollte man sich im vorfeld gedanken machen. Hat man zum Beispiel ein 10 MB Objekt in der Session liegen, so ist es unter umständen unperformanter die komplette Session inklusive Objekt bei jedem Statuswechsel auf Dateisysemebene durchzuparsen.

  6. tcomic sagt:

    @Leif: Ja ich meinte den „Präsentierteller“ 😉 Aber ein Witz war das nicht, ich habe mir gestern kurz befor ich diesen Artikel gesehen habe wirklich Gedanken darüber gemacht…

  7. GhostGambler sagt:

    Also ich persönliche lasse meine Objekte lieber entweder komplett direkt auf dem Session-Array werkeln, oder stecke noch eine weitere Klasse dazwischen, welche einen abstrakten Zugriff auf die Session bereit stellt.
    Warum?
    Damit ich zum Beispiel auch von anderen Applikationen ohne Probleme auf die Benutzer-ID in der Session zugreifen kann.

    Übrigens, 10 MB Große Objekte sollten eigentlich eh nichts in der Session zu suchen haben…
    Man stelle sich mal vor, eine Website mit 4000 aktiven Benutzern, dann hat man mal eben 40.000 MB (heißt 40 GB) an Session-Daten.
    In welchem RAM sollen die passen? Memcache wird da wenig Freude dran haben…
    Ins Dateisystem passt das schon deutlich besser, aber … naja … was will man denn in 10 MB alles speichern? Da dauert das Parsen der Textdateien im Dateisystem (und ja, es sind normale Textdateien – das Session-Array wird mit serialize bearbeitet auf der Festplatte gespeichert) ja länger als der sonstige Skriptaufruf…

    Für Standard-Anforderungen reicht die Benutzer-ID und der Benutzername. Für komplizierte Rechte-Systeme noch ein paar Strings/IDs für die Rechte.
    Sagen wir mal noch ein paar andere Daten, dann kommt man maximal auf ein MB, vielleicht leicht darüber, das sollte eigentlich für normale Zwecke durchaus ausreichen.

  8. Sebastian sagt:

    gott da fehlt ja die hälfte.

    mittels den magischen funktionen __sleep() und __wakeup kann ich steuern was mittels serialize, was der php standard session handler ist, gespeichert wird. und den sollte ich auch nutzen.
    dadurch kann ich nur das speichern was gebraucht wird. deswegen kann ich hier nicht von performance sprechen, sondern eher von bequemlichkeit. in verbindung mit mvc mgl. ganz nützlich, aber ein reger anwendungsfall ist mir dafür noch nicht unterlaufen.

    zum memory: bei session ist der normalerweise nicht nötig. wenn du mehr als 500kb daten zusammenbekommst hast du entweder einen riesen text oder, was wahrscheinlicher ist, ein bild oä. und genau das hat nichts in der session zu suchen. darin speichert man minimaldaten!

  9. chris sagt:

    ich hab die „__autoload“ funktion nach dem „session_start()“

    funktioniert einwandfrei …

    wie performant jetzt autoload ist, darüber lässt sich streiten 🙂

  10. Simon sagt:

    Wie schaut es denn aus wenn man Datenbank-Verbindungen in der Session speichern will so das die nicht immer neu erstellt werden müssen?

    Bleiben die für die Zeit für die diese vom SQL-Server offen gehalten werden erhalten oder gehen die nach dem Durchlauf des Scripts verloren?

  11. admin sagt:

    Wenn Du nicht bei jedem seitenaufruf die DB-Connection neu öffnen möchtest, solltest Du persistente Verbindungen nehmen. Vorher empfehle ich allerdings die Information über max_connections. Ist die maximale Anzahl Verbindungen nämlich aufgebraucht, wird der nächste Besucher einfach im Regen stehen gelassen.

    Die PHP-Funktion dazu lautet mysql_pconnect().

  12. GhostGambler sagt:

    Man kann keine Resourcen in der Session speichern. Genauso wenig wie Referenzen.

    Übrigens rate ich von mysql_pconnect() ab.
    Bei MySQL sind die Kosten zum Öffnen einer neuen Verbindung so gering, dass die Nachteile eindeutig überwiegen. (Unnötig gebrauchte, aber trotzdem belegte Verbindungen. Man kann zwar max_connections hoch setzen, dann wiederum öffnet man aber Tür und Tor dafür, dass sich der Datenbankserver selbst lahm legt.)

  13. floid sagt:

    Hallo..

    diese Methodik klingt ja sehr interessant. Genau das gleiche hab ich mir auch schon überlegt. Nur das ich meine User Objekte der eingeloggten user dort unterbringe. Sodass ich nicht bei jedem Request erneut in die Datenbank muss um den User zu holen.
    Der Nachteil aber das ich den User nicht immer aktuell habe. Dies regle ich über eine loged_in_user_table in welchem ich nachschaue ob der User der sich gerade den Request hat irgendwelche neue Daten aus der Datenbank lesen muss..

    Was glaubt IHR ? Sparre ich mit dieser Methode viel Peformace ?

  14. GhostGambler sagt:

    Potentiell sollte doch eh nur jeder Benutzer selbst seine Daten ändern. In dem Fall kannst du das Objekt direkt aktualisieren.

    Für den Fall, dass tatsächlich einmal Daten von „extern“ aktualisiert werden müssen, kannst du die Benutzer-ID doch noch einmal manuell im Datensatz speichern und den Datensatz dann einfach leeren lassen. Das Objekt merkt, hey, ich bin leer, und konstruiert aus der user-id im Datensatz das Objekt einfach neu.
    Das spart dir die zusätzliche Tabelle.

  15. Latita sagt:

    Ah, vielen Dank für diesen Artikel.
    Ich bin hier bald verrückt geworden ^^ Ich wusste, dass man Objekte in Sessions speichern kann, bekam nach einem Post aber nur einen Fehler *argh* ^^
    Jetzt muss ich in deinem Blog mal stöbern gehen, ob du auch was zur Serialisierung von Objekten geschrieben hast 🙂

  16. Nadini sagt:

    hey! ich habe mich erst kürzlich damit beschäftigt und mit schrecken festgestellt, dass das Objekt bei jeden neuem request einfach neu erstellt wird. bis ich dann von selbst auf die idee kam, dass objekt in eine session zu stecken und dann wieder in ein neu erstelltes objekt zu legen. finde es sehr unelegant …

Eine Antwort schreiben

Ihre E-Mail-Adresse wird nicht veröffentlicht. Benötigte Felder sind markiert mit *

You may use these HTML tags and attributes: <a href=""> <blockquote cite=""> <pre lang=""> <b> <strong> <i> <em>