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 :

[Singleton] pb de compréhension


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juillet 2004
    Messages
    28
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 28
    Par défaut [Singleton] pb de compréhension
    Bonjour,

    J'ai créée une classe singleton, qui me semble avoir un problème: à chaque fois que je transmet le formulaire l'instance est remise à zéro.

    Au lieu de récupérer une instance créée une fois pour toute, la classe singleton agit comme une classe qui ne l'est pas...
    ci-dessous mon code:

    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
     
    <?php
     
    	// nom de fichier : bug_sgl.php
     
     
    	// recuperation valeur
     
    	Sgl::Instance()->Load();
     
    	echo "<html><head></head><body>";
    	echo "<br>Valeur de retour:(".Sgl::Instance()->mValeur.")";
     
    	echo "<form name=test action=bug_sgl.php  method='get'>";
    	echo "<input type ='submit' value='envoi' name='toto' />";
    	echo "<input type ='hidden' value='retour' name='lavaleur' />";
    	echo "</form>";
    	echo "</body></html>";
     
     
    	class Sgl {
     
    		static protected $mInstance;
    		static public $mCompteur;
     
    		public $mValeur;
     
    		protected function __construct( ) {	}
    		protected function __destruct( ) { echo"<br> bye bye";	}
     
    		public function Instance() {
    			self::$mCompteur++;
    			if( is_null(self::$mInstance) ){
    				self::$mInstance = new Sgl();
    				echo "<br>Sgl:::Creation de l'instance n°(".self::$mCompteur.")";
    			} else {
    				echo "<br>Sgl::Récupération de l'instance n°(".self::$mCompteur.")";
    			}
    				return self::$mInstance;
    		}
     
    		public function Load() {
    			$this->mValeur =   isset($_GET['lavaleur'])  ?  $_GET['lavaleur'] : null ;
    		}
     
    	}
    ?>

    l'affichage en sortie donne :

    Sgl:::Creation de l'instance n°(1)
    Sgl::Récupération de l'instance n°(1)
    Valeur de retourretour)

    Warning: Call to protected Sgl::__destruct() from context '' during shutdown ignored in Unknown on line 0
    - le compteur initialisé dans la classe sert de marqueur, il n'est incrémenté qu'une fois. Le problème c'est qu'il ne devrait pas l'être à envoi de formulaire.


    Mes questions :
    - Comment faire pour avoir un comportement du singleton habituel (l'instance est créée une seule fois) ?
    - Comment éviter l'appel au destructeur ?

    Merci de vos réponses

  2. #2
    Membre Expert

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Par défaut
    Contrairement a un autre langage de programmation, les classes de PHP ne sont pas persistés en mémoire d'un appel d'une page a une autre.

    Si c'était le cas, il serait difficile de savoir quand libérer la mémoire (si tu ferme brutalement ton navigateur, le site n'est pas au courant que la mémoire doit être libérée)

    Ta classe singleton n'est un singleton qu'au sein d'une seule requete HTTP d'un utilisateur.
    Si tu appelles plusieurs fois getInstance dans ton code php au sein d'une même requete HTTP alors tu récupèrera le même objet.

    => Si tu veux une donnée qui soit persistée de page en page pour UN utilisateur il faut que tu utilises soit un cookie, soit une session.

    => Si tu veux une donnée qui soit persistée de page en page pour TOUT les utilisateurs, il faut que tu utilise une base de donnée ou un fichier.


    Concernant le destructeur, il doit être appelé a la fin de la requete HTTP pour libérer la mémoire, et l'appel sort en erreur car il n'est pas public.
    Dans ton cas, laisse PHP gérer la mémoire, et sauf si tu en as réellement besoin, laisse tomber le destructeur.

  3. #3
    Membre averti
    Inscrit en
    Juillet 2004
    Messages
    28
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 28
    Par défaut
    Merci pour ta réponse.

    Si je stocke mon instance singleton dans une variable de session, Php va quand même faire un appel au destructeur à l'envoi du formulaire pour libérer la mémoire?

    Est-il possible de désactiver cet appel juste pour cette instance, et de gérer moi-même la vie de mon instance?

  4. #4
    Membre Expert

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Par défaut
    Tu ne peux pas empêcher PHP de détruire ton instance (sauf peut être si tu utilises des trucs compliqués comme la mémoire partagée, mais a moins de savoir exactement ce que tu fait et d'avoir accès a la configuration de ton serveur, on oublie ^^)

    En session tu ne peux pas stocker une instance, mais uniquement du texte.
    => Soit tu stockes directement la ou les données correspondant a ton singleton
    => Soit tu t'amuse a serialiser/deserialiser ton objet dans ta session

    Personnellement, tant que ton singleton est simple, je te conseille d'utiliser la session a la place.
    Et quand je dis "a la place", c'est pas "en plus".
    Bref, supprimer ton singleton et utiliser la session a la place.

    Ou alors, si tu veux utiliser les 2 (mais c'est inutile a mon avis), tu fait un "faux" singleton qui est mappé sur la session genre :
    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
    public class MonSingleton {
      static private $mpInstance = new MonSingleton(); // au passage, initialiser un singleton de cette manière est mieux que de le faire dans getInstance
     
      public getInstance() {
        return self::$mpInstance;
      }
     
      protected __construct() {
      }
     
      public get($pKey) {
        return $_SESSION[pKey];
      }
     
      public put($pKey, $pValue) {
        $_SESSION[$pKey]=$pValue;
      }
    }

  5. #5
    Membre Expert
    Avatar de ThomasR
    Homme Profil pro
    Directeur technique
    Inscrit en
    Décembre 2007
    Messages
    2 230
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 2 230
    Par défaut
    Bonjour,

    Contrairement à ce qui est dit plus haut tu peux stocker ton objet en session.

    Penses-juste que si dans cette classe tu as des références vers d'autres objets elles seront perdues. Pour palier à çà il faut dans la méthode __sleep définir quelles membres tu gardent en session, et dans la méthode __wakeup revaloriser les membres.

  6. #6
    Membre Expert

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Par défaut
    Citation Envoyé par ThomasR Voir le message
    Contrairement à ce qui est dit plus haut tu peux stocker ton objet en session.
    Oui, tu peux avec des méthodes magiques de PHP, mais en fait ca revient a stocker du texte (serialiser/deserialiser les attributs non objets) et a demander a PHP de "reconstruire" l'objet sur la nouvelle page.

    Par contre, la notion de singleton telle qu'on l'entend normalement, c'est a dire un objet UNIQUE, ne survivra pas si on le met en session. L'adresse de l'objet sera différente même si pour le développeur il a l'impression de manipuler le même objet.

  7. #7
    Membre averti
    Inscrit en
    Juillet 2004
    Messages
    28
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 28
    Par défaut
    OK c'est déjà plus clair, merci pour vos réponses.

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

Discussions similaires

  1. Compréhension de fseek
    Par Argonz dans le forum C
    Réponses: 9
    Dernier message: 12/01/2004, 15h01
  2. compréhension du profil d'une fonction
    Par lor dans le forum MFC
    Réponses: 7
    Dernier message: 08/01/2004, 12h59
  3. [FLASH MX] Prob de compréhension des bouttons
    Par WriteLN dans le forum Flash
    Réponses: 13
    Dernier message: 16/10/2003, 17h01
  4. onclipevent (problème de compréhension)
    Par stephane eyskens dans le forum Flash
    Réponses: 8
    Dernier message: 24/09/2003, 15h09
  5. Problème de compréhension des ensembles
    Par Cornell dans le forum Langage
    Réponses: 6
    Dernier message: 07/02/2003, 22h07

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