Précédent   Forum des professionnels en informatique > PHP > Langage > Sessions
Sessions Forum d'entraide sur les sessions avec PHP. Avant de poster -> FAQ sessions, Cours sessions et Sources sécurité
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 21/06/2007, 18h45   #1
Membre régulier
 
Avatar de knoodrake
 
Inscription : juin 2007
Messages : 86
Détails du profil
Informations personnelles :
Âge : 26
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations forums :
Inscription : juin 2007
Messages : 86
Points : 74
Points : 74
Par défaut [Sessions/objets] Sauvegarde d'objets: devient StdClass apres delinearisation

EDIT: Solution aux posts #4 (et #5)

Bonjour a tous.

J'ai un objet "$user->panier", que je serialize pour rentrer dans une variable de session. Probleme, lorsque je "unserialize" l'object, il devient un object de la StdClass et ne me sert donc plus a rien.
Pourtant, la définition de la classe PANIER (celle de l'objet) est faite AVANT le session_start(), etc..

Le petit soupson que j'ai: l'objet $user->panier est créé, comme vous pouvez le voir, DANS le constructeur de la classe USER. c'est dans cette même classe USER qu'elle est sérializée et unsérializée. Ca pourai venir de la ?

Bon, bref, voici le code.

La fameuse classe qui renit son objet (la méchante!):
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 
<?php
class PANIER
{
	public $articles = array();
	public $date_dodo = 0;
 
	public function __get ($name) {
		$value = null;
		if ($name == "nombre_d_articles") {
			$value = $this->nombre_d_articles();
		} elseif ($name == "total") {
			$value = $this->get_total();
		} elseif ($name == "articles") {
			$value = $this->articles;
		} else {
			if (!isset($this->articles[$name])) $value = 0;
			else $value = $this->articles[$name];
		}
		return $value;
	}
 
	public function __set ($name,$value) {
		$this->articles[$name] = $value;
		return true;
	}
	public function remove ($name) {
		unset($this->aricles[$name]);
		return true;
	}
 
	public function nombre_d_articles () {
		return array_sum($this->articles);
	}
 
	// retourne le prix total
	public function get_total () {
		$db = DB::getMe();
		$total = 0;
		foreach ($this->articles as $k => $v)
			$total += PRODUIT::prix($k) * $v;
		return $total;
	}
 
	public function __sleep () {
		foreach ($this->articles as $k => $v)
			if ($v <= 0) unset($this->articles[$k]);
		$this->date_dodo = time();
	}
}
?>
la classe USER au travers de laquelle la classe PANIER est manipulé:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
 
 
class USER
{
	private static $instance;
 
	private function __construct ($login) {
		$db = DB::getMe();
		// a proteger !! //
		$q = "SELECT * FROM `client` WHERE `login` = '$login'";
		$r = $db->queryfetchobject($q);
 
		$this->nom = $r->nom;
		$this->prenom = $r->prenom;
		$this->login = $r->login;
		$this->password = $r->password;
		$this->mail = $r->mail;
		/* etc.. */
 
		// restore le panier 
		$this->panier = new PANIER ();
		if (!empty($_SESSION['cart']))
			$this->panier = unserialize($_SESSION['cart']);
	}
 
	public static function getMe ($login=null) {
		if (!empty($login))
			self::$instance = new USER ($login);
		elseif (empty(self::$instance))
			self::$instance = new USER ($_SESSION['login']);
		return	self::$instance;
	}
 
	public function ajouter_au_panier($id,$qte) {
		if (isset($this->panier->{"id".$id})) {
			$this->panier->{"id".$id} += $qte;
		} else 	$this->panier->{"id".$id}  = $qte;
 
		$this->backup_panier();
	}
 
	public function enlever_du_panier($id,$qte) {
		if (isset($this->panier->{"id".$id})) {
			$this->panier->{"id".$id} -= $qte;
			if ($this->panier->{"id".$id}<=0)
				$this->panier->remove("id".$id);
		}
		$this->backup_panier();
	}
 
	private function backup_panier() {
		if (!empty($this->panier)) {
			$panier = serialize($this->panier);
			$_SESSION['cart'] = $panier;
		} else unset ($_SESSION['cart']);
	}
 
	public function __destruct () {
		$this->backup_panier();
	}
}
 
?>
et le lieu du crime:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
<?php
require ("inc/panier.class.php");
require ("inc/user.class.php");
session_start();
require ("include.php"); // le reste du programme.
 
/* .. 
	reste de la page 
.. */
 
$user = USER::getMe();
echo "<pre>";print_r($_SESSION);echo"</pre>";
/*
 *  Et cette ligne ci dessu, donne ( le drame !) :
 * [ ...blabla..] 
 * [cart] => O:8:"stdClass":1:{s:4:"id26";i:1;} <-- StdClass :'-(
 * [..blabla..]
 *
*/
?>

Donc si quelqu'un pouvait m'aider, ou m'indiquer un piste de recherche, quelque chose..

Merci par avance.

Cordialement, Damien.
knoodrake est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/06/2007, 21h40   #2
Membre émérite
 
Avatar de viviboss
 
Inscription : août 2006
Messages : 943
Détails du profil
Informations personnelles :
Âge : 30
Localisation : France, Gard (Languedoc Roussillon)

Informations forums :
Inscription : août 2006
Messages : 943
Points : 941
Points : 941
PHP est un langage de script, et s'interprete de haut en bas, et de gaucha à droite.

Pourquoi ton session_start() est si bas ? Pourquoi ne le mets-tu pas au début ?

Dans ta classe USER, tu utilises des variables de SESSION, sans qu'elles soient déclarer....

Conseil : session_start au début, essaye....

Je fais à peu près les même choses (même si je préfère sérializer et unserializer à l'extérieur des classes....), mais mes includes de classes je les faits juste après le session_start().

PS : petite question : pourquoi ne pas, d'ailleur, faire hériter USER de PANIER ?

Enfin, c'est juste une question omme ca....
__________________
Veni Vidi Vici
-------------------------
Mes articles : developpez.com ou bien vbview.net
-------------------------
Et SURTOUT ne pas oublier la bible PHP : --> php_manual_fr.chm!!!
Et aussi : --> pear_manual_fr.chm!!!

Ou encore : --> Les tutoriaux & cours PHP de Développez.com
-------------------------
viviboss est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 16h39   #3
Membre régulier
 
Avatar de knoodrake
 
Inscription : juin 2007
Messages : 86
Détails du profil
Informations personnelles :
Âge : 26
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations forums :
Inscription : juin 2007
Messages : 86
Points : 74
Points : 74
Merci pour cette réponse rapide (et désolé la mienne pas rapide.. fête de la musique oblige )


Citation:
PHP est un langage de script, et s'interprete de haut en bas, et de gaucha à droite.

Pourquoi ton session_start() est si bas ? Pourquoi ne le mets-tu pas au début ?
Parcque j'ai lu quelque part sur ce forum que la définition de la classe a délinéariser devait se faire avant le session_start().
Quoi qu'il en soit, qu'il soit avant ou après ne change rien.

Citation:
Dans ta classe USER, tu utilises des variables de SESSION, sans qu'elles soient déclarer....
Hein ? quoi que qui ?
Mais la aussi, quoi qu'il en soit, les session ormis ce probleme de StdClass marchent très bien comme ça. on peu se logger, rester logger, etc.. et quand on ajoute un truc au panier, le truc est bien ajouté au panier, le panier reste etc.. sauf que le panier ne marche pas car il n'a plus de méthodes :-/
M'enfin, pas de probleme du côté des sessions visiblement.
Citation:
PS : petite question : pourquoi ne pas, d'ailleur, faire hériter USER de PANIER ?
J'y ai pensé. faudra que j'y re-pense (voir si ça m'apporte quelque chose).
knoodrake est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 17h04   #4
En attente de confirmation mail
 
Inscription : juin 2002
Messages : 6 164
Détails du profil
Informations forums :
Inscription : juin 2002
Messages : 6 164
Points : 6 404
Points : 6 404
Citation:
Envoyé par knoodrake
Parce que j'ai lu quelque part sur ce forum que la définition de la classe a délinéariser devait se faire avant le session_start().
Quoi qu'il en soit, qu'il soit avant ou après ne change rien.
Parce que vous faites vous-mêmes cette sérialisation (appel aux fonctions serialize et unserialize), ce que fais déjà PHP (du coup vos variables sont (dé)sérialisés deux fois en tout) et l'emplacement des déclarations ne doit jouer, dans votre code, que lors du unserialize, je suppose. Sérialisez-vous toutes vos données, quelles qu'elles soient ?

Je serais intéressé par un dump complet de vos variables de session. Est-ce possible d'en avoir un ?
julp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 17h16   #5
Membre régulier
 
Avatar de knoodrake
 
Inscription : juin 2007
Messages : 86
Détails du profil
Informations personnelles :
Âge : 26
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations forums :
Inscription : juin 2007
Messages : 86
Points : 74
Points : 74
Code :
1
2
$user = USER::getMe();
	echo "<pre>";var_dump($_SESSION);echo"</pre>";
done : (enfin, une fois la méthode $user->ajoute_au_panier($id) executée au moins une fois)
Code :
1
2
3
4
5
6
7
8
array(3) {
  ["sessionkey"]=>
  &string(32) "bd20ebd606f16f01fe45e7c733e00b49"
  ["login"]=>
  &string(6) "client"
  ["cart"]=>
  &string(34) "O:8:"stdClass":1:{s:4:"id26";i:1;}"
}
julp, ce que vous voulez dire, c'est que lorsque je fait $_SESSION['var']=$obj , $obj est automatiquement linéarisé par php, et idem pour la délinéarisation ?

Edit: PS: j'ai la configuration par defaut de XAMPP Linux.
knoodrake est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 17h22   #6
Membre Expert
 
Inscription : janvier 2005
Messages : 2 288
Détails du profil
Informations forums :
Inscription : janvier 2005
Messages : 2 288
Points : 2 287
Points : 2 287
Je vais peut-etre dire une betise ou tout mélanger, mais il me semblait qu'il fallait coder les méthodes __sleep() et __wake() pour les classes que l'on souhaiter pouvoir (dé)sérialiser dans les sessions, non?
koopajah est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 17h25   #7
Membre régulier
 
Avatar de knoodrake
 
Inscription : juin 2007
Messages : 86
Détails du profil
Informations personnelles :
Âge : 26
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations forums :
Inscription : juin 2007
Messages : 86
Points : 74
Points : 74
Citation:
Envoyé par koopajah
Je vais peut-etre dire une betise ou tout mélanger, mais il me semblait qu'il fallait coder les méthodes __sleep() et __wake() pour les classes que l'on souhaiter pouvoir (dé)sérialiser dans les sessions, non?
Non, c'est optionel. PHP lors d'un (dé)linéarisation va essayer d'apeller __sleep() et __wakeup().
knoodrake est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 17h41   #8
En attente de confirmation mail
 
Inscription : juin 2002
Messages : 6 164
Détails du profil
Informations forums :
Inscription : juin 2002
Messages : 6 164
Points : 6 404
Points : 6 404
Citation:
Envoyé par knoodrake
julp, ce que vous voulez dire, c'est que lorsque je fait $_SESSION['var']=$obj , $obj est automatiquement linéarisé par php, et idem pour la délinéarisation ?
Bien sûr, comme toute variable. Vous ne sérialisez pas vos chaînes ou vos variables numériques lorsque vous les utiliser dans une session ? C'est la même chose, la seule restriction est celle que vous avez évoqué : la(les) déclaration(s) des classes doivent être faites avant session_start.

D'autre part, votre méthode __sleep est erronée puisque PHP attend qu'on lui retourne un tableau : vous devriez avoir une erreur (de type notice).

Quelle version de PHP utilisez-vous ?
julp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 17h53   #9
Membre régulier
 
Avatar de knoodrake
 
Inscription : juin 2007
Messages : 86
Détails du profil
Informations personnelles :
Âge : 26
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations forums :
Inscription : juin 2007
Messages : 86
Points : 74
Points : 74
Youpi !
J'ai donc viré les fonctions serialize et unserialize et maintenant j'ai encore plein de nouveaux problemes, mais mon objet reste "lui-même"
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
array(3) {
  ["sessionkey"]=>
  &string(32) "bd20ebd606f16f01fe45e7c733e00b49"
  ["login"]=>
  &string(6) "client"
  ["cart"]=>
  &object(PANIER)#5 (2) {
    ["articles"]=>
    array(1) {
      ["id26"]=>
      int(1)
    }
    ["date_dodo"]=>
    int(0)
  }
}
Donc la c'est ok visiblement. Merci infiniment a tous.

julp: j'utilise PHP 5.2.1, et comme précisé plus haut, avec les parametres de la distribution php/sql XAMPP. ..et je n'ai aucune notice.
De plus, si je regarde la documentation a ce propos , je peu voir:
Citation:
Exemple 19.27. Utilisation de Sleep et de wakeup
Code :
1
2
3
4
5
6
7
 
/* reste de l'exemple .. */
public function __sleep()
    {
        mysql_close($this->link);
    }
/* reste de l'exemple.. */
donc pas de tableau retourné
knoodrake est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 18h18   #10
En attente de confirmation mail
 
Inscription : juin 2002
Messages : 6 164
Détails du profil
Informations forums :
Inscription : juin 2002
Messages : 6 164
Points : 6 404
Points : 6 404
L'explication à l'obtention de stdClass serait la suivante d'après la doc :
Citation:
Envoyé par http://fr.php.net/manual/fr/language.oop.serialization.php
Si vous utilisez les sessions et la fonction session_register() pour sauver des objets, ces objets seront linéarisés automatiquement avec la fonction serialize() à la fin de chaque script, et relus avec unserialize() au début du prochain script. Cela signifie que ces objets peuvent apparaître dans n'importe quelle page qui utilise vos sessions.

Il est vivement recommandé d'inclure la définition de classe dans toutes vos pages, même si vous n'utilisez pas ces classes dans toutes vos pages. Si vous l'oubliez et qu'un tel objet est présent, il perdra sa classe, et deviendra un objet de classe stdClass sans aucune fonction et, donc, plutôt inutile.
C'est là qu'on remarque qu'elle n'est pas très à jour (session_register étant dépréciée). Vous, sérialisant manuellement en plus l'objet, cela ne pouvait, en toute logique, se produire que lors de vos appels à serialize/unserialize.
julp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 18h31   #11
Membre émérite
 
Avatar de viviboss
 
Inscription : août 2006
Messages : 943
Détails du profil
Informations personnelles :
Âge : 30
Localisation : France, Gard (Languedoc Roussillon)

Informations forums :
Inscription : août 2006
Messages : 943
Points : 941
Points : 941
C'est bizarre, j'ai jamais eu ces problèmes alors que je sérialise et désérialise manuellement, et ce en ayant mes déclarations de classes APRES le Session_Start().....

Ba, tant mieux pour moi

Au fait, une petite question : j'ai lu quelque part que l'auto_load des classes allait être déprécié, est-ce vrai ? Si oui, pourquoi ? (C'est bien pratique quand même...)
__________________
Veni Vidi Vici
-------------------------
Mes articles : developpez.com ou bien vbview.net
-------------------------
Et SURTOUT ne pas oublier la bible PHP : --> php_manual_fr.chm!!!
Et aussi : --> pear_manual_fr.chm!!!

Ou encore : --> Les tutoriaux & cours PHP de Développez.com
-------------------------
viviboss est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 19h14   #12
Membre régulier
 
Avatar de knoodrake
 
Inscription : juin 2007
Messages : 86
Détails du profil
Informations personnelles :
Âge : 26
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations forums :
Inscription : juin 2007
Messages : 86
Points : 74
Points : 74
Citation:
Envoyé par viviboss
C'est bizarre, j'ai jamais eu ces problèmes alors que je sérialise et désérialise manuellement, et ce en ayant mes déclarations de classes APRES le Session_Start()...
Mais tes objets linéarisés, tu les met bien dans des variables de session ? (pas dans ta BDD, dans un fichier, .. )
knoodrake est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 19h31   #13
Membre émérite
 
Avatar de viviboss
 
Inscription : août 2006
Messages : 943
Détails du profil
Informations personnelles :
Âge : 30
Localisation : France, Gard (Languedoc Roussillon)

Informations forums :
Inscription : août 2006
Messages : 943
Points : 941
Points : 941
Oui, c'est pour cela que je sérialise (Je ne met pas mes objets en BDD) : je les passes d'une page à l'autre comme ca...
__________________
Veni Vidi Vici
-------------------------
Mes articles : developpez.com ou bien vbview.net
-------------------------
Et SURTOUT ne pas oublier la bible PHP : --> php_manual_fr.chm!!!
Et aussi : --> pear_manual_fr.chm!!!

Ou encore : --> Les tutoriaux & cours PHP de Développez.com
-------------------------
viviboss est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 19h49   #14
Membre régulier
 
Avatar de knoodrake
 
Inscription : juin 2007
Messages : 86
Détails du profil
Informations personnelles :
Âge : 26
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations forums :
Inscription : juin 2007
Messages : 86
Points : 74
Points : 74
Citation:
Envoyé par julp
D'autre part, votre méthode __sleep est erronée puisque PHP attend qu'on lui retourne un tableau : vous devriez avoir une erreur (de type notice).
Citation:
donc pas de tableau retourné
Autant pour moi.
En fait, PHP n'attend pas spécialement qu'on lui retourne un tableaux. Il n'attend un tableaux que dans le cas ou __sleep() sert a retourner l'objet (son utilisation logique et courant en bref), mais rien n'empeche de retourner autre chose a PHP, auquel cas, le "autre chose" sera mis dans la variable de session.

C'est pour cela que je n'ai eu aucun Warning ou Notice.
Cela veut aussi dire que vous aviez raison, mon __sleep() est érroné, ou du moins au vu de l'utilisation que j'en fait. Merci encore pour votre aide précieuse.

Citation:
Oui, c'est pour cela que je sérialise
alors.. mystère.. peut-être une directive comme celle-ci dans le php.ini: "unserialize_callback_func" ? mystère et bulle de gume
knoodrake est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 03h17.


 
 
 
 
Partenaires

Hébergement Web