web-dev-qa-db-fra.com

Stocker des objets dans PHP session

La documentation PHP indique: "Vous ne pouvez pas utiliser de références dans les variables de session car il n'existe aucun moyen réaliste de restaurer une référence à une autre variable."

Est-ce que cela signifie que je ne peux pas avoir des choses comme:

session_start();
$user = new User;
$user->name = 'blah';
$_SESSION['user'] = $user;

J'ai essayé de stocker une chaîne simple et un objet Utilisateur en session. Cette chaîne persiste toujours entre les pages ou après l'actualisation de la page. Cependant, la variable User est perdue dans $ _SESSION (devient vide).

une idée?

Edit: J'ai confirmé que session_id est identique dans toutes ces pages/sous-pages, avant et après l'actualisation de la page.

Edit: Bizarrement, après avoir essayé l’approche sérialisée et non sérialisée ci-dessous, l’objet utilisateur sérialisé (ou chaîne) de la session disparaît toujours!

Edit: Enfin, j’ai compris ce que le bogue était, on dirait que $ _SESSION ["utilisateur"] est écrasé par une force mystérieuse, si j’utilise une variable autre que "utilisateur", tout va bien. PHP (au moins la version 5.3 que j'utilise) sérialise et désérialise automatiquement lorsque vous placez un objet dans $ _SESSION.

session_start();
$user = new User();
$user->name = 'blah'
$_SESSION['myuser'] = $user; 
30
user157195

Vous devez utiliser les méthodes magic __sleep et __wakeup pour PHP 5 objets.

Par exemple dans le bloc de code suivant:

$obj = new Object();

$_SESSION['obj'] = serialize($obj);

$obj = unserialize($_SESSION['obj']);

__sleep est appelé par serialize (). Une méthode de veille renverra un tableau des valeurs de l'objet que vous souhaitez conserver.

__wakeup est appelé par unserialize (). Une méthode de réveil doit prendre les valeurs non sérialisées et les initialiser dans l'objet.

49
Noah Goodrich

Votre exemple de code n'utilise pas de références car la documentation faisait référence à. C'est ce que php entend par références :

$var =& $GLOBALS["var"];

Pour ce qui est de placer des objets dans la session, PHP can peut stocker des objets dans $_SESSION. Voir http://example.preinheimer.com/sessobj.php .

Ce que vous voyez est un bug dans l'ordre des appels à __sleep et __destruct (__destruct est appelé avant __sleep) et le module de session ne parvient pas à sérialiser l'objet à l'arrêt. Ce bug a été ouvert le 1 septembre 2009.

2
JPot

Vous aviez raison de dire que vous ne pouvez pas stocker de références dans les variables de session Assigner un objet dans PHP 5 et au dessus revient à faire cela, assigner la référence et non l'obj

C'est pourquoi vous devez sérialiser l'objet (en implémentant également __sleep dans la classe) et en affectant la chaîne à une variable de session.

et en le désérialisant plus tard (en implémentant aussi __wake dans la classe) à partir de la variable de session.

1
jose segura

Pour une sérialisation sécurisée et une désérialisation, codez et décodez avec base64_encode () et base64_decode () respectivement. Ci-dessous, je passe un objet sérialisé à une session et le désérialise sur l'autre page pour rétablir la variable dans un état d'objet.

Page 1

<?php

require  $_SERVER['DOCUMENT_ROOT'] .'/classes/RegistrationClass.php';
$registrationData= new RegistrationClass();
$registrationData->setUserRegData();
$reg_serlizer = base64_encode(serialize($registrationData));   //serilize the object to create a string representation
$_SESSION['regSession'] = $reg_serlizer;
?>

Page 2

<?php
session_start();
require  $_SERVER['DOCUMENT_ROOT'] .'/classes/RegistrationClass.php';
$reg_unserilizeObj = 
unserialize((base64_decode($_SESSION['regSession'])));
$reg_unserilizeObj->firstName;
?>

Cet article décrit les problèmes auxquels le non-respectqui peut être confronté . problèmes de sérialisation/de désérialisation php

0
Kirk Patrick Brown

C'est le comportement attendu. Le stockage d'une référence à un objet ne fonctionnerait que si l'emplacement de la mémoire pour l'objet ne changeait pas. Dans un protocole sans état tel que HTTP, l'état de l'application n'est pas conservé entre les demandes. La demande suivante peut être gérée sur un autre thread, processus ou un autre serveur. 

Compte tenu de la nature intrinsèque d'une application Web sans état, il est inutile de maintenir un pointeur sur un emplacement de mémoire. Par conséquent, l'état de l'objet doit être décomposé en un format de stockage, enregistré ou transmis, puis reconstitué si nécessaire. Ce processus s'appelle Sérialisation

Vous pouvez choisir de sérialiser l'objet entier en session (ce qui peut être dangereux en fonction de la profondeur de votre graphe d'objet, car votre objet peut contenir des références à d'autres objets et celles-ci doivent également être sérialisées), ou si l'objet peut être reconstitué en interrogeant la base de données à la demande suivante, vous pouvez simplement cacher un identifiant dans la session.

[MODIFIER]

JPot a souligné que les objets sont automatiquement sérialisés vers $ _SESSION. Une sérialisation explicite n'est donc pas nécessaire. Je laisserai la réponse à la postérité, mais évidemment, cela n'aidera pas votre problème.

0
gbc