web-dev-qa-db-fra.com

PHP: Stocker des 'objets' dans la $ _SESSION

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

Je sais que si je n'avais qu'un seul point d'entrée, je n'aurais pas besoin de le faire mais je n'y suis pas encore. Je n'ai donc pas un seul point d'entrée et j'aimerais vraiment garder mon objet car je ne le fais pas. pas 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, cela pose-t-il des problèmes?


Modifier:

Résumé temporaire : Je comprends maintenant que c'est probablement il est préférable de recréer l'objet même s'il s'agit d'interroger à nouveau la base de données.

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

182
markus

Je sais que ce sujet est ancien, mais ce problème ne cesse de se poser et n'a pas encore été abordé à ma satisfaction:

Que vous sauvegardiez des objets dans $ _SESSION ou les reconstruisiez en fonction de données stockées dans des champs de formulaire masqués, ou que vous les interrogiez à nouveau à partir de la base de données, vous utilisiez state. HTTP est sans état (plus ou moins; voir GET vs. PUT), mais presque tout ce que quelqu'un veut faire avec une application Web nécessite que l'état soit maintenu quelque part. Agir comme si pousser l'État dans les coins et les recoins équivaut à une sorte de victoire théorique, c'est tout simplement faux. L'état est l'état. Si vous utilisez state, vous perdez les différents avantages techniques acquis en étant apatride. Ce n'est pas quelque chose à perdre sommeil à moins que vous sachiez à l'avance que vous devriez perdre le sommeil à cause de cela.

Je suis particulièrement déconcerté par la bénédiction reçue par les arguments du "double coup dur" avancés par Hank Gay. Le PO construit-il un système de commerce électronique distribué et équilibré? Je suppose que non. et j'ajouterai que la sérialisation de sa classe $ User, ou autre, ne paralysera pas son serveur de manière irréversible. Mon conseil: utilisez des techniques sensibles à votre application. Les objets dans $ _SESSION sont corrects, sous réserve des 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.

128
shanusmagnus

c'est correct tant que, au moment où l'appel session_start () est effectué, la déclaration/définition de classe a déjà été rencontrée par PHP ou peut être trouvée par un autochargeur déjà installé. Sinon, ne pas être en mesure de désérialiser l'objet à partir du magasin de session.

112
cruizer

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.

UPDATE: Il n'y a pas de concept de session au niveau HTTP; les serveurs fournissent cela en donnant au client un ID unique et en lui demandant de le soumettre à chaque demande. Ensuite, le serveur utilise cet ID en tant que 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 sur l'évolutivité (une des principales raisons pour lesquelles HTTP est sans état).

  • Whammy One: Cela réduit le travail qu'un seul serveur peut faire.
  • Whammy Two: Cela rend plus difficile le dimensionnement car maintenant, vous ne pouvez plus simplement acheminer une requête à un ancien serveur - ils n'ont pas tous la même session. Vous pouvez épingler toutes les demandes portant un ID de session donné sur le même serveur. Ce n'est pas facile, et c'est un point d'échec unique (pas pour le système dans son ensemble, mais pour les gros morceaux de vos utilisateurs). Ou bien, vous pouvez partager le stockage de session sur tous les serveurs du cluster, mais vous avez maintenant plus de complexité: mémoire attaché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). En outre, 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 qu'absolument nécessaire dans la session.

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

(Vinko ajoute: PHP peut utiliser une base de données pour stocker les informations de session. Demander au client de soumettre à nouveau les données à chaque fois peut résoudre d'éventuels problèmes d'évolutivité, mais ouvre la porte à de nombreux problèmes de sécurité. à présent que le client contrôle tout votre état)

35
Hank Gay
  • Les objets qui ne peuvent pas être sérialisés (ou qui contiennent des membres non sérialisables) ne sortiront pas de la $ _SESSION comme prévu
  • Des sessions énormes alourdissent le serveur (la sérialisation et la désérialisation de méga-états sont coûteuses à chaque fois)

Autre que cela, je n'ai vu aucun problème.

18
Vinko Vrsalovic

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

9
Greg

Je suggérerais de ne pas utiliser l'état à moins d'en avoir 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 requête, 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 la session (exemple: l'utilisateur doit rester connecté pendant sa session le l'application web). Enfin, je suggèrerais de garder votre objet de session aussi petit que possible car il impacte les performances pour sérialiser et désérialiser des objets volumineux.

6
Johnny

N'oubliez pas que les types de ressources (telles 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.

Prenez également en compte la taille de la session. Selon la manière dont elle est stockée, vous pouvez avoir des restrictions de taille ou des problèmes de latence.

4
Marc Gear

Je voulais également parler de la mise à niveau des bibliothèques de logiciels - nous avons mis à niveau notre logiciel et l'ancienne version contenait des objets en session avec les noms de classe du logiciel V1, le nouveau logiciel se bloquait lorsqu'il tentait de créer les objets qui se trouvaient dans la session - comme V2 le logiciel n'utilisait plus ces mêmes classes, il ne pouvait pas les trouver. Nous avons dû mettre un code correctif pour détecter les objets de session, supprimer la session si elle est trouvée, recharger la page. Au départ, la plus grande douleur que vous ayez eu à faire était de recréer ce bogue lorsqu’il a été signalé (trop familier, "eh bien, ça marche pour moi" :) car il ne concernait que les personnes qui utilisaient et réinstallaient l’ancien et le nouveau système récemment - mais bon travail que nous avions trouvé avant le lancement car tous nos utilisateurs auraient sûrement eu les anciennes variables de session dans leurs sessions et se seraient potentiellement écrasés pour tous, cela aurait été un terrible lancement :)

Quoi qu'il en soit, comme vous le suggérez dans votre amendement, je pense aussi qu'il est préférable de recréer l'objet. Donc, peut-être que le simple stockage de l'identifiant, puis à chaque demande, extrayant l'objet de la base de données, est préférable/plus sûr.

0
Martyn