PHP: Speichern von 'Objekten' in der $ _SESSION

188

Ich habe gerade herausgefunden, dass ich tatsächlich Objekte in der $ _SESSION speichern kann und finde es ziemlich cool, weil ich immer noch mein Objekt habe, wenn ich zu einer anderen Seite springe. Bevor ich diesen Ansatz verwende, möchte ich herausfinden, ob dies wirklich eine so gute Idee ist oder ob potenzielle Fallstricke bestehen .

Ich weiß, wenn ich einen einzigen Einstiegspunkt hätte, müsste ich das nicht tun, aber ich bin noch nicht da, also habe ich keinen einzigen Einstiegspunkt und würde mein Objekt wirklich gerne behalten, weil ich es nicht tue. Ich verliere meinen Zustand nicht so. (Jetzt habe ich auch gelesen, dass ich zustandslose Websites programmieren sollte, aber ich verstehe dieses Konzept noch nicht.)

Also kurz gesagt : Ist es in Ordnung , zum Speichern von Objekten in der Sitzung, gibt es irgendwelche Probleme mit ihm?


Bearbeiten:

Temporäre Zusammenfassung : Mittlerweile ist es wahrscheinlich besser, das Objekt neu zu erstellen, auch wenn die Datenbank erneut abgefragt wird.

Weitere Antworten könnten diesen Aspekt vielleicht etwas näher erläutern !

Markus
quelle
13
Wie 'dumm' ich 2008 war :-)
Markus
49
aber nützliche Frage an 'dumm wie wir im Jahr 2014: D
Momin Al Aziz
3
Sehr schöne Fragen, die Sie Markus gestellt haben .. :) Ich habe es heute gelesen;)
gkd
1
Du warst nicht dumm! Sie haben gefragt, was ich fragen wollte, und haben mir 10 Jahre später einen soliden Eindruck gemacht!
Toddmo
Nun, ich schätze, Sie haben mich gerade
Maxwell,

Antworten:

133

Ich weiß, dass dieses Thema alt ist, aber dieses Problem taucht immer wieder auf und wurde nicht zu meiner Zufriedenheit angesprochen:

Unabhängig davon, ob Sie Objekte in $ _SESSION speichern oder sie anhand von Daten, die in ausgeblendeten Formularfeldern gespeichert sind, als Ganzes rekonstruieren oder jedes Mal aus der Datenbank abfragen, verwenden Sie state. HTTP ist zustandslos (mehr oder weniger; siehe jedoch GET vs. PUT), aber fast alles, was jemand mit einer Web-App tun möchte, erfordert, dass der Status irgendwo beibehalten wird. Es ist einfach falsch, so zu tun, als würde man den Staat in Ecken und Kanten drängen. Staat ist Staat. Wenn Sie state verwenden, verlieren Sie die verschiedenen technischen Vorteile, die sich aus der Statuslosigkeit ergeben. Dies ist nichts, worüber Sie den Schlaf verlieren können, es sei denn, Sie wissen im Voraus, dass Sie den Schlaf verlieren sollten.

Ich bin besonders verblüfft über den Segen, den die von Hank Gay vorgebrachten "Double Whammy" -Argumente erhalten haben. Baut das OP ein verteiltes und lastausgeglichenes E-Commerce-System auf? Meine Vermutung ist nein; und ich werde weiter davon ausgehen, dass die Serialisierung seiner $ User-Klasse oder was auch immer seinen Server nicht irreparabel lähmen wird. Mein Rat: Verwenden Sie Techniken, die für Ihre Anwendung sinnvoll sind. Objekte in $ _SESSION sind in Ordnung, vorbehaltlich der Vorsichtsmaßnahmen des gesunden Menschenverstandes. Wenn sich Ihre App plötzlich in etwas verwandelt, das mit Amazon im Datenverkehr konkurriert, müssen Sie sich neu anpassen. So ist das Leben.

Shanusmagnus
quelle
16
Schöne Antwort, die viele meiner eigenen Gedanken enthält, während ich dies durchgelesen habe. Das moderne Internet braucht Staat. Während einige Anwendungen keinen Status benötigen und sinnvoll sind, um zustandslos erstellt zu werden, stützt sich das moderne Internet auf zu viele Systeme, die auf dem Status basieren (AKA: Logins!), Um sie einfach aufzugeben! Die großen Götter des Internets haben dieses Grundkonzept sogar jahrelang in Form von Cookies integriert und auf einer grundlegenden Ebene in Form von lokalem Speicher in HTML hinzugefügt. Es kann sinnvoll sein, in einigen Anwendungen eine übermäßige Verwendung des Status zu vermeiden, in einigen jedoch! = Alle!
RonLugge
Nun, als ich diese Frage stellte, kurz nachdem der Mensch das Feuer erfunden hatte, wusste ich nicht viel, was ich heute weiß ... was auch gut so ist. In der Zwischenzeit würde ich sagen, dass es einige gute Anwendungsfälle gibt, aber im Allgemeinen würde ich zuerst nach anderen Lösungen suchen. Markieren Sie dies immer noch als die neu akzeptierte Antwort, da die andere Antwort zu kategorisch ist.
Markus
Sehr wenige Antworten bringen mich zum Lachen. Dieser tat es. Bravo +1
toddmo
114

Es ist in Ordnung, solange zum Zeitpunkt des Aufrufs von session_start () die Klassendeklaration / -definition bereits von PHP gefunden wurde oder von einem bereits installierten Autoloader gefunden werden kann. Andernfalls kann das Objekt nicht aus dem Sitzungsspeicher deserialisiert werden.

Kreuzer
quelle
12
Vielen Dank! Das hat einen Fehler für mich behoben: D
Matt Ellen
Ich gehe davon aus, dass dieses Problem vermieden werden könnte, wenn Sie eine ordnungsgemäße __autoload()Funktion haben.
Langel
Müssen wir beim Unserialisieren eines serialisierten Objekts die Klassendefinition hinzufügen? Zum Zeitpunkt der Serialisierung des Objekts benötigt es die Klassendefinition, der ich zustimme. Muss ich die Klassendefinition auch in die Datei einfügen, in der ich das serialisierte Objekt unserialisieren muss?
Rajesh Paul
35

HTTP ist aus einem bestimmten Grund ein zustandsloses Protokoll. Sitzungen schweißen den Status auf HTTP. Vermeiden Sie als Faustregel die Verwendung des Sitzungsstatus.

UPDATE: Es gibt kein Konzept für eine Sitzung auf HTTP-Ebene. Server stellen dies bereit, indem sie dem Client eine eindeutige ID geben und ihn anweisen, diese bei jeder Anforderung erneut zu senden. Dann verwendet der Server diese ID als Schlüssel für eine große Hashtabelle von Sitzungsobjekten. Immer wenn der Server eine Anfrage erhält, sucht er die Sitzungsinformationen aus seiner Hashtabelle der Sitzungsobjekte basierend auf der ID, die der Client mit der Anfrage gesendet hat. All diese zusätzliche Arbeit ist ein Doppelschlag in Bezug auf die Skalierbarkeit (ein wichtiger Grund, warum HTTP zustandslos ist).

  • Whammy One: Es reduziert die Arbeit, die ein einzelner Server leisten kann.
  • Whammy Two: Das Skalieren wird schwieriger, da Sie jetzt eine Anfrage nicht einfach an einen alten Server weiterleiten können - sie haben nicht alle dieselbe Sitzung. Sie können alle Anforderungen mit einer bestimmten Sitzungs-ID an denselben Server anheften. Das ist nicht einfach und ein einziger Fehlerpunkt (nicht für das gesamte System, sondern für große Teile Ihrer Benutzer). Sie können den Sitzungsspeicher auch für alle Server im Cluster freigeben, aber jetzt sind Sie komplexer: an das Netzwerk angeschlossener Speicher, ein eigenständiger Sitzungsserver usw.

Vor diesem Hintergrund ist der Einfluss auf die Leistung umso größer, je mehr Informationen Sie in die Sitzung einfügen (wie Vinko betont). Wie Vinko betont, verhält sich die Sitzung schlecht, wenn Ihr Objekt nicht serialisierbar ist. Vermeiden Sie daher als Faustregel, mehr als unbedingt erforderlich in die Sitzung aufzunehmen.

@Vinko Normalerweise können Sie den Serverspeicherstatus umgehen, indem Sie die Daten, die Sie verfolgen, in die zurückgesendete Antwort einbetten und vom Client erneut senden lassen, z. B. indem Sie die Daten in einer versteckten Eingabe senden. Wenn Sie wirklich eine serverseitige Statusverfolgung benötigen, sollte sich diese wahrscheinlich in Ihrem Sicherungsdatenspeicher befinden.

(Vinko fügt hinzu: PHP kann eine Datenbank zum Speichern von Sitzungsinformationen verwenden. Wenn der Client die Daten jedes Mal erneut übermittelt, können potenzielle Skalierbarkeitsprobleme behoben werden. Es wird jedoch eine große Anzahl von Sicherheitsproblemen geöffnet, auf die Sie jetzt achten müssen, da der Client die Kontrolle über alle hat Ihr Staat)

Hank Gay
quelle
1
Es gibt kein Konzept für eine Sitzung auf HTTP-Ebene. Server stellen dies bereit, indem sie dem Client eine eindeutige ID geben und ihn anweisen, diese bei jeder Anforderung erneut zu senden. Dann verwendet der Server diese ID als Schlüssel für eine große Hashtabelle von Sitzungsobjekten. Fortsetzung
Hank Gay
1
Immer wenn der Server eine Anfrage erhält, sucht er die Sitzungsinformationen aus seiner Hashtabelle der Sitzungsobjekte basierend auf der ID, die der Client mit der Anfrage gesendet hat. All diese zusätzliche Arbeit ist ein Doppelschlag in Bezug auf die Skalierbarkeit (ein wichtiger Grund, warum HTTP zustandslos ist). Fortsetzung
Hank Gay
1
Ich frage mich, wie Sie komplexe Anwendungen über HTTP ohne Schweißzustand irgendwie implementieren würden
Vinko Vrsalovic
3
Bitte bearbeiten Sie Ihre Antwort, um alle diese Kommentare aufzunehmen. Es ist einfacher zu lesen und besser für das Wiki und trotzdem kann ich Ihre Antwort nicht als die akzeptierte wählen, wenn alles Wichtige in den Kommentaren steht. Vielen Dank!
Markus
6
"whammy one" Ich wünschte, ich könnte dies mehr ablehnen. Kennen Sie Ihr Timing. Eine Speicherreferenz kostet 100 Nanosekunden oder 0,0001 ms. Das Nachschlagen einer Hashtabelle, die im Hauptspeicher gespeichert ist, kostet also buchstäblich keine Zeit. Erzählt O(1)dir etwas? @whammy zwei: Leiten Sie nicht alle Anfragen zufällig an zufällige Server weiter? Führen Sie Round Robin durch und leiten Sie das Routing von demselben Benutzer an denselben Server weiter. Das ist wow, super offensichtlich. Sie müssen Ihre Bücher zusammen mit allen über 30 Upvotes noch
einmal
19
  • Objekte, die nicht serialisiert werden können (oder die unserialisierbare Mitglieder enthalten), werden nicht wie erwartet aus $ _SESSION entfernt
  • Riesige Sitzungen belasten den Server (das Serialisieren und Deserialisieren von Status-Megas jedes Mal ist teuer).

Ansonsten habe ich keine Probleme gesehen.

Vinko Vrsalovic
quelle
9

Nach meiner Erfahrung lohnt es sich im Allgemeinen nicht für etwas Komplizierteres als eine StdClass mit einigen Eigenschaften. Die Kosten für die Unserialisierung waren immer höher als die Neuerstellung aus einer Datenbank mit einer in einer Sitzung gespeicherten Kennung. Es scheint cool zu sein, aber (wie immer) ist die Profilerstellung der Schlüssel.

Greg
quelle
Gibt es einen Kommentar zu den Leistungen zwischen dem Abfragen einer 5x2-Datentabelle bei jeder Anforderung und dem Zwischenspeichern des Ergebnisses in der Sitzung und dessen Verwendung?
musicliftsme
6

Ich würde vorschlagen, nicht state zu verwenden, es sei denn, Sie brauchen es unbedingt. Wenn Sie das Objekt ohne Sitzungen neu erstellen können, tun Sie dies. Wenn Sie Status in Ihrer Webanwendung haben, wird die Erstellung der Anwendung komplexer. Bei jeder Anforderung müssen Sie sehen, in welchem ​​Status sich der Benutzer befindet. Natürlich gibt es Zeiten, in denen Sie die Verwendung der Sitzung nicht vermeiden können (Beispiel: Der Benutzer muss während seiner Sitzung angemeldet bleiben die Webanwendung). Zuletzt würde ich vorschlagen, Ihr Sitzungsobjekt so klein wie möglich zu halten, da dies die Leistung beim Serialisieren und Unserialisieren großer Objekte beeinträchtigt.

Johnny
quelle
Ist es also besser, das Objekt neu zu erstellen und alle Datenbankabfragen erneut auszuführen? Weil einer meiner Gedanken dafür war, dass ich die Datenbank nicht noch einmal nach dem gleichen Zeug abfragen muss.
Markus
3
Wenn es Ihnen wichtig ist, dass die Datenbank nicht erneut abgefragt wird, verwenden Sie das Caching, anstatt sie in der Sitzung zu speichern. Aber bitte überprüfen Sie vor dem Erstellen von Caching, ob es sich wirklich um einen Leistungseinbruch handelt.
Johnny
Danke, ich denke eigentlich nicht. Ich sollte einfach noch einmal abfragen.
Markus
4

Sie müssen sich daran erinnern, dass Ressourcentypen (wie Datenbankverbindungen oder Dateizeiger) zwischen dem Laden von Seiten nicht bestehen bleiben, und Sie müssen diese unsichtbar neu erstellen.

Berücksichtigen Sie auch die Größe der Sitzung, je nachdem, wie sie gespeichert ist. Möglicherweise treten Größenbeschränkungen oder Latenzprobleme auf.

Marc Gear
quelle
0

Ich würde auch beim Aktualisieren von Softwarebibliotheken darauf hinweisen - wir haben unsere Software aktualisiert und die alte Version hatte Objekte in Sitzung mit den Klassennamen der V1-Software. Die neue Software stürzte ab, als sie versuchte, die Objekte in der Sitzung zu erstellen - als V2 Software verwendete nicht mehr dieselben Klassen, sie konnte sie nicht finden. Wir mussten einen Fixcode eingeben, um Sitzungsobjekte zu erkennen, die Sitzung zu löschen, falls gefunden, und die Seite neu zu laden. Der größte Schmerz anfangs war, dass Sie diesen Fehler neu erstellt haben, als er zum ersten Mal gemeldet wurde (allzu vertraut, "nun, es funktioniert für mich" :), da er nur Leute betraf, die in letzter Zeit in die alten und neuen Systeme ein- und ausgingen - jedoch gut Job, den wir vor dem Start gefunden haben, da alle unsere Benutzer sicherlich die alten Sitzungsvariablen in ihren Sitzungen gehabt hätten und möglicherweise für alle abgestürzt wären.

Wie Sie in Ihrem Änderungsantrag vorschlagen, ist es meines Erachtens auch besser, das Objekt neu zu erstellen. Vielleicht ist es besser / sicherer, nur die ID zu speichern und dann bei jeder Anforderung das Objekt aus der Datenbank zu ziehen.

Martyn
quelle