PHP: stocker des 'objets' dans la $ _SESSION

188

Je viens de comprendre que je peux en fait stocker des objets dans la $ _SESSION et je trouve ça plutôt cool parce que quand je passe à une autre page, j'ai toujours mon objet. Maintenant, avant de commencer à utiliser cette approche, j'aimerais savoir si c'est vraiment une si bonne idée ou s'il y a des pièges potentiels .

Je sais que si j'avais un seul point d'entrée je n'aurais pas besoin de le faire mais je n'y suis pas encore donc je n'ai pas un seul point d'entrée et j'aimerais vraiment garder mon objet parce que je ne le fais pas ' t perdre mon état comme ça. (Maintenant, j'ai aussi lu que je devrais programmer des sites sans état mais je ne comprends pas encore ce concept.)

Donc en bref : est-il possible de stocker des objets dans la session, y a-t-il des problèmes?


Éditer:

Résumé temporaire : à présent, je comprends qu'il est probablement préférable de recréer l'objet même si cela implique d'interroger à nouveau la base de données.

D'autres réponses pourraient peut-être développer un peu plus cet aspect !

Markus
la source
13
Comme j'étais `` stupide '' en 2008 :-)
Markus
49
mais question utile aux `` stupides comme nous en 2014: D
Momin Al Aziz
3
Très belles questions que vous avez posées à markus .. :) Je l'ai lu aujourd'hui;)
gkd
1
Tu n'étais pas stupide! Vous m'avez demandé ce que j'allais demander et vous m'avez fait du solide, 10 ans plus tard!
toddmo
eh bien, je suppose que vous venez de m'éviter de poser une question stupide en 2019
Maxwell

Réponses:

133

Je sais que ce sujet est ancien, mais ce problème revient sans cesse et n'a pas été résolu à ma satisfaction:

Que vous sauvegardiez des objets dans $ _SESSION, ou que vous les reconstruisiez entièrement en fonction des données stockées dans des champs de formulaire masqués, ou que vous les interrogiez à nouveau à partir de la base de données à chaque fois, vous utilisez state. HTTP est sans état (plus ou moins; mais voir GET vs PUT) mais presque tout ce que quiconque s'intéresse à une application Web nécessite que l'état soit maintenu quelque part. Agir comme si pousser l'État dans des recoins équivaut à une sorte de victoire théorique est tout simplement faux. L'État est l'État. Si vous utilisez l'état, vous perdez les divers avantages techniques que vous procure le fait d'être apatride. Ce n'est pas quelque chose à perdre le sommeil à moins que vous ne sachiez à l'avance que vous devriez perdre le sommeil à cause de cela.

Je suis particulièrement décontenancé par la bénédiction reçue par les arguments du «double coup dur» avancés par Hank Gay. Le PO est-il en train de construire un système de commerce électronique distribué et équilibré? Ma conjecture est non; et je postulerai en outre que la sérialisation de sa classe $ User, ou autre, ne paralysera pas son serveur de manière irréparable. Mon conseil: utilisez des techniques adaptées à votre application. Les objets dans $ _SESSION conviennent, sous réserve de précautions de bon sens. Si votre application se transforme soudainement en quelque chose qui rivalise avec Amazon en termes de trafic, vous devrez vous réadapter. C'est la vie.

Shanusmagnus
la source
16
Belle réponse incorporant beaucoup de mes propres pensées pendant que je lisais ceci. L'Internet moderne a besoin d'un état. Alors que certaines applications n'ont pas besoin d'état et ont du sens à être créées de manière apatride, Internet moderne repose sur trop de systèmes basés sur l'état (AKA: Logins!) Pour les abandonner! Les grands dieux de l'Internet ont même incorporé ce concept de base pendant des années sous la forme de cookies, et à un niveau de base, ils l'ont ajouté sous la forme d'un stockage local en HTML. Il peut être judicieux d'éviter une utilisation excessive de l'état dans certaines applications, mais certaines! = All!
RonLugge
Eh bien, quand j'ai posé cette question peu de temps après que l'homme a inventé le feu, je ne savais pas beaucoup de choses que je sais aujourd'hui ... ce qui est tout aussi bien. En attendant, je dirais qu'il peut y avoir quelques bons cas d'utilisation, mais en général, je chercherais d'abord d'autres solutions. Toujours marquer cela comme la nouvelle réponse acceptée car l'autre réponse est catégorique.
markus
Très peu de réponses me font rire aux éclats. Celui-ci l'a fait. Bravo +1
toddmo
114

c'est OK tant qu'au moment de l'appel session_start (), la déclaration / définition de classe a déjà été rencontrée par PHP ou peut être trouvée par un autoloader déjà installé. sinon, il ne serait pas en mesure de désérialiser l'objet du magasin de sessions.

cruizer
la source
12
Merci! Cela a corrigé un bug pour moi: D
Matt Ellen
Je suppose que ce problème pourrait être évité si vous avez une __autoload()fonction appropriée .
Langel
Pour désérialiser un objet sérialisé, devons-nous ajouter la définition de classe ??? Au moment de la sérialisation de l'objet, il a besoin de la définition de classe, que je suis d'accord, mais dois-je ajouter la définition de classe également dans le fichier où je dois désérialiser l'objet sérialisé ???
Rajesh Paul
35

HTTP est un protocole sans état pour une raison. Les sessions soudent l'état sur HTTP. En règle générale, évitez d'utiliser l'état de session.

MISE À JOUR: Il n'y a pas de concept de session au niveau HTTP; les serveurs fournissent cela en donnant au client un identifiant unique et en disant au client de le soumettre à nouveau à chaque demande. Ensuite, le serveur utilise cet ID comme clé dans une grande table de hachage d'objets Session. Chaque fois que le serveur reçoit une demande, il recherche les informations de session dans sa table de hachage d'objets de session en fonction de l'ID que le client a soumis avec la demande. Tout ce travail supplémentaire est un double coup dur sur l'évolutivité (une grande raison pour laquelle HTTP est sans état).

  • Whammy One: Cela réduit le travail qu'un seul serveur peut faire.
  • Whammy Two: Cela rend la mise à l'échelle plus difficile car maintenant vous ne pouvez plus simplement acheminer une requête vers n'importe quel ancien serveur - ils n'ont pas tous la même session. Vous pouvez épingler toutes les demandes avec un ID de session donné sur le même serveur. Ce n'est pas facile, et c'est un point de défaillance unique (pas pour le système dans son ensemble, mais pour de gros morceaux de vos utilisateurs). Vous pouvez également partager le stockage de session sur tous les serveurs du cluster, mais vous avez désormais plus de complexité: mémoire connectée au réseau, serveur de session autonome, etc.

Compte tenu de tout cela, plus vous mettez d'informations dans la session, plus l'impact sur les performances est important (comme le souligne Vinko). Comme le souligne Vinko, si votre objet n'est pas sérialisable, la session se comportera mal. Donc, en règle générale, évitez de mettre plus que ce qui est absolument nécessaire dans la session.

@Vinko Vous pouvez généralement contourner l'état de stockage du serveur en incorporant les données que vous suivez dans la réponse que vous renvoyez et en demandant au client de la resoumettre, par exemple, en envoyant les données dans une entrée masquée. Si vous avez vraiment besoin d'un suivi de l'état côté serveur, il devrait probablement se trouver dans votre banque de données de sauvegarde.

(Vinko ajoute: PHP peut utiliser une base de données pour stocker les informations de session, et demander au client de resoumettre les données à chaque fois peut résoudre des problèmes d'évolutivité potentiels, mais ouvre un grand nombre de problèmes de sécurité auxquels vous devez faire attention maintenant que le client contrôle tout ton état)

Hank Gay
la source
1
Il n'y a pas de concept de session au niveau HTTP; les serveurs fournissent cela en donnant au client un identifiant unique et en disant au client de le soumettre à nouveau à chaque demande. Ensuite, le serveur utilise cet ID comme clé dans une grande table de hachage d'objets Session. A suivre…
Hank Gay
1
Chaque fois que le serveur reçoit une demande, il recherche les informations de session dans sa table de hachage d'objets de session en fonction de l'ID soumis par le client avec la demande. Tout ce travail supplémentaire est un double coup dur sur l'évolutivité (une grande raison pour laquelle HTTP est sans état). A suivre…
Hank Gay
1
Je me demande comment implémenter des applications complexes sur HTTP sans état de soudage en quelque sorte
Vinko Vrsalovic
3
veuillez modifier votre réponse pour inclure tous ces commentaires. c'est plus facile à lire et meilleur pour le wiki et de toute façon je ne peux pas choisir votre réponse comme acceptée, si tout ce qui est important est dans les commentaires. Merci!
markus
6
"whammy one" Je souhaite que je pourrais contrevoter davantage. Connaissez votre timing. Une référence mémoire coûte 100 nanosecondes, soit 0,0001 ms. Ainsi, faire une recherche sur une table de hachage stockée dans la mémoire principale ne coûte littéralement pas de temps. Ne O(1)vous dire quelque chose? @whammy two: ne pas acheminer au hasard toutes les requêtes vers des serveurs aléatoires? faire un tourniquet et continuer le routage vers le même serveur à partir du même utilisateur. C'est wow, super évident. Vous devez revenir sur vos livres, ainsi que sur les 30 votes positifs
Toskan
19
  • Les objets qui ne peuvent pas être sérialisés (ou qui contiennent des membres non sérialisables) ne sortiront pas de $ _SESSION comme vous vous en doutez
  • Les sessions énormes pèsent sur le serveur (sérialiser et désérialiser des mégas d'état à chaque fois coûte cher)

A part ça, je n'ai vu aucun problème.

Vinko Vrsalovic
la source
9

D'après mon expérience, cela ne vaut généralement pas la peine pour quelque chose de plus compliqué qu'une StdClass avec certaines propriétés. Le coût de la désérialisation a toujours été plus que la recréation à partir d'une base de données à partir d'un identifiant stocké en session. Cela semble cool, mais (comme toujours), le profilage est la clé.

Greg
la source
Un commentaire sur les performances entre l'interrogation d'une table de données 5x2 à chaque demande et la mise en cache du résultat en session et son utilisation?
musicliftsme
6

Je suggérerais de ne pas utiliser state sauf si vous en avez absolument besoin. Si vous pouvez reconstruire l'objet sans utiliser de sessions, faites-le. Avoir des états dans votre application Web rend l'application plus complexe à construire, pour chaque demande, vous devez voir dans quel état se trouve l'utilisateur. Bien sûr, il y a des moments où vous ne pouvez pas éviter d'utiliser session (exemple: l'utilisateur doit rester connecté pendant sa session sur l'application web). Enfin, je suggérerais de garder votre objet de session aussi petit que possible car cela a un impact sur les performances de sérialisation et de désérialisation d'objets volumineux.

Johnny
la source
Alors, est-il préférable de reconstruire l'objet en effectuant à nouveau toutes les requêtes de base de données? Parce que l'une de mes pensées pour faire cela est que je n'ai plus à interroger la base de données pour les mêmes choses.
markus le
3
S'il est important pour vous de ne plus interroger la base de données, utilisez la mise en cache au lieu de la stocker dans la session. Mais avant de faire quoi que ce soit comme la création de la mise en cache, vérifiez s'il s'agit vraiment d'un problème de performances.
Johnny
Merci, je pense en fait que non. Je devrais simplement demander à nouveau.
markus
4

Vous devrez vous rappeler que les types de ressources (tels que les connexions à la base de données ou les pointeurs de fichiers) ne persisteront pas entre les chargements de page, et vous devrez les recréer de manière invisible.

Tenez également compte de la taille de la session, selon la façon dont elle est stockée, vous pouvez avoir des restrictions de taille ou des problèmes de latence.

Marc Gear
la source
0

J'évoquerais également lors de la mise à niveau des bibliothèques de logiciels - nous avons mis à niveau notre logiciel et l'ancienne version avait des objets en session avec les noms de classe du logiciel V1, le nouveau logiciel plantait quand il a essayé de construire les objets qui étaient dans la session - comme le V2 le logiciel n'utilisait plus ces mêmes classes, il ne pouvait plus les trouver. Nous avons dû mettre un code de correction pour détecter les objets de session, supprimer la session si elle est trouvée, recharger la page. La plus grande douleur au départ, c'est que vous avez recréé ce bogue quand il a été signalé pour la première fois (trop familier, "eh bien, ça marche pour moi" :) car il n'affectait que les personnes qui étaient dans et hors des anciens et des nouveaux systèmes récemment - cependant, bien travail que nous avons trouvé avant le lancement car tous nos utilisateurs auraient sûrement eu les anciennes variables de session dans leurs sessions et auraient potentiellement planté pour tous,

Quoi qu'il en soit, comme vous le suggérez dans votre amendement, je pense aussi qu'il vaut mieux recréer l'objet. Alors peut-être que simplement stocker l'id, puis à chaque demande extraire l'objet de la base de données, est meilleur / plus sûr.

Martyn
la source