IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

[Sessions/objets] Sauvegarde d'objets: devient StdClass apres delinearisation


Sujet :

Langage PHP

  1. #1
    Membre régulier Avatar de knoodrake
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    86
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2007
    Messages : 86
    Points : 86
    Points
    86
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

  2. #2
    Membre éprouvé
    Avatar de viviboss
    Profil pro
    Inscrit en
    Août 2006
    Messages
    943
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Gard (Languedoc Roussillon)

    Informations forums :
    Inscription : Août 2006
    Messages : 943
    Points : 1 248
    Points
    1 248
    Par défaut
    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
    -------------------------

  3. #3
    Membre régulier Avatar de knoodrake
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    86
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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


    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.

    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.
    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).

  4. #4
    Expert éminent sénior

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    6 152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 6 152
    Points : 17 778
    Points
    17 778
    Par défaut
    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 ?

  5. #5
    Membre régulier Avatar de knoodrake
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    86
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2007
    Messages : 86
    Points : 86
    Points
    86
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

  6. #6
    Membre expert
    Inscrit en
    Janvier 2005
    Messages
    2 291
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 291
    Points : 3 212
    Points
    3 212
    Par défaut
    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?

  7. #7
    Membre régulier Avatar de knoodrake
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    86
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2007
    Messages : 86
    Points : 86
    Points
    86
    Par défaut
    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().

  8. #8
    Expert éminent sénior

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    6 152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 6 152
    Points : 17 778
    Points
    17 778
    Par défaut
    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 ?

  9. #9
    Membre régulier Avatar de knoodrake
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    86
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2007
    Messages : 86
    Points : 86
    Points
    86
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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:
    Exemple 19.27. Utilisation de Sleep et de wakeup
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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é

  10. #10
    Expert éminent sénior

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    6 152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 6 152
    Points : 17 778
    Points
    17 778
    Par défaut
    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.

  11. #11
    Membre éprouvé
    Avatar de viviboss
    Profil pro
    Inscrit en
    Août 2006
    Messages
    943
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Gard (Languedoc Roussillon)

    Informations forums :
    Inscription : Août 2006
    Messages : 943
    Points : 1 248
    Points
    1 248
    Par défaut
    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
    -------------------------

  12. #12
    Membre régulier Avatar de knoodrake
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    86
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2007
    Messages : 86
    Points : 86
    Points
    86
    Par défaut
    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, .. )

  13. #13
    Membre éprouvé
    Avatar de viviboss
    Profil pro
    Inscrit en
    Août 2006
    Messages
    943
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Gard (Languedoc Roussillon)

    Informations forums :
    Inscription : Août 2006
    Messages : 943
    Points : 1 248
    Points
    1 248
    Par défaut
    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
    -------------------------

  14. #14
    Membre régulier Avatar de knoodrake
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    86
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2007
    Messages : 86
    Points : 86
    Points
    86
    Par défaut
    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).
    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.

    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

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Architecture / Services] Graphe d'objets à sauvegarder
    Par mauvais_karma dans le forum Plateformes (Java EE, Jakarta EE, Spring) et Serveurs
    Réponses: 5
    Dernier message: 05/03/2006, 16h07
  2. [POO] sauvegarde d'objets et perte des methodes
    Par Matth_S dans le forum Langage
    Réponses: 3
    Dernier message: 23/12/2005, 15h47
  3. Réponses: 4
    Dernier message: 14/09/2005, 21h39
  4. sauvegarder un objet au format .x
    Par sylvain_bos dans le forum DirectX
    Réponses: 3
    Dernier message: 19/08/2004, 23h05
  5. [arbre] Sauvegarder un objet dans un fichier
    Par Guigui_ dans le forum Langage
    Réponses: 6
    Dernier message: 07/02/2003, 00h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo