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 :

Conception problématique avec Singleton


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de MegaBigBoss
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    144
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 144
    Par défaut Conception problématique avec Singleton
    Bonsoir à vous !

    Alors, je viens vous voir car j'ai quelques difficultés avec un singleton ( bien que je pense en avoir saisi le concept de base ).

    Je souhaite entamer un projet, mais afin de décider quelle architecture employer, pour faire quelque chose qui sera évolutif au possible, à travers des systèmes de plugins une bdd sql, j'ai décidé de faire quelques tests, parce que c'est l'un de mes premiers projets qui nécessite des choses du genre, et c'est donc la première fois que j'utilise un singleton.

    Ainsi voilà mon problème, j'obtiens l'erreur
    ( ! ) Fatal error: Maximum function nesting level of '100' reached, aborting! in C:\Wamp\www\Tests\includes\test.class.php on line 65
    , lorsque j'execute ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $CityHandler = cityHandler::getInstance();
    Voici la déclaration de la classe, ainsi que des classes impliquées.
    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
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    <?php
    abstract class building
    {
    	var $id;
    	var $name;
    	var $description;
    	var $cost;
    	var $city_id;
    	var $cityHandler;
     
    	function addAction($id)
    	{
    		// Action : Nom, Description, Ce qui est affiché, Conditions, Pour qui ?
    	}
     
    	abstract function onConstructionStarted(); // A faire dans la ville quand construction commencée
    	abstract function onConstructionFinished(); // A faire dans la ville quand construction terminée
    	abstract function onDestruction();
     
    }
     
    class bank extends building
    {
    	function __construct($id, $city_id)
    	{
    		$this->id = $id;
    		$this->city_id = $city_id;
    		$this->name = "Banque";
    		$this->description = "Une superbe banque";
    		$this->cost['pts'] = 100;
    		$this->cityHandler = cityHandler::getInstance();
    	}
     
    	function onConstructionStarted()
    	{
    		return;
    	}
     
    	function onConstructionFinished()
    	{
    		print('Banque construite !');
    	}
     
    	function onDestruction()
    	{
    		return;
    	}
    }
     
    class city
    {
    	var $id;
    	var $name; 
    	var $action; // Actions possible dans la ville, liées à la ville ?
    	var $offres; // Emplois
     
    	var $_events; // Flux d'informations ?
    	var $_buildings; // Batiments
    	var $_hooks; // Hooks
     
    	function __construct($id)
    	{
    		$this->id = $id;
     
    		$this->load();
    		$this->updateBuildings();
    	}
     
    	function load()
    	{
    		global $db;
     
    		$qry_loadHooks = $db->prepare("SELECT * FROM city_hooks");
    		$qry_loadHooks->execute();
     
    		while($row = $qry_loadHooks->fetch(PDO::FETCH_ASSOC))
    		{
    			$this->_hooks[$row['category']][] = $row['name'];
     
    		}
     
    		// Buildings
    		/*$qry_loadBuildings = $db->prepare("SELECT * FROM city_buildings");
    		$qry_loadBuildings->execute();
    		
    		while($row = $qry_loadBuildings->fetch(PDO::FETCH_ASSOC))
    		{
    			//buildingManager::getBuildingClass($building_id)
    		}*/
     
    		$this->_buildings[] = new bank(1, $this->id);
    	}
     
    	function addEvent($text)
    	{
    		$this->_events[] = $text;
    	}
     
    	function isConstructionFinished()
    	{
    		return true;
    	}	
     
    	function updateBuildings()
    	{
    		foreach($this->_buildings as $building)
    		{
    			foreach ($this->_hooks['buildings'] as $hookName)
    			{
    				if(is_callable(array($building, 'on'.$hookName)) && is_callable(array($this, 'is'.$hookName)))
    				{
    					if(call_user_func(array($this, 'is'.$hookName)) == true)
    					{
    						call_user_func(array($building, 'on'.$hookName));
    					}
    				}
    			}
    		}
    	}
    }
     
    class cityHandler
    {
    	/**
    	* @var Singleton
    	* @access private
    	* @static
    	*/
    	private static $instance = null;
     
    	static $cities = null;
     
    	private function __construct()
    	{
    		global $db;
     
    		if(self::$instance == null)
    		{
    			$query_load = $db->prepare("SELECT id FROM city");
    			$query_load->execute();
     
    			while($row = $query_load->fetch(PDO::FETCH_ASSOC))
    			{
    				$this->cities[$row['id']] = new city($row['id']);
    			}
    		}
    	}
     
    	public static function getInstance() 
    	{
    		if (!isset(self::$instance)) {
                $c = __CLASS__;
                self::$instance = new $c;
            }
    	}
     
    	public function addEvent($text, $city_id)
    	{
    		$this->cities[$city_id]->addEvent($text);
    	}
     
    	public function getCity($city_id)
    	{
    		return $this->cities[$city_id];
    	}
     
    	public function __clone()
            {
                    trigger_error('Tentative de clonage', E_USER_ERROR);
            }
    }
    ?>
    Je pense que c'est un soucis de conception, étant donné que l'instanciation de ma classe CityHandler, déclare toutes les villes, qui déclarent un objet bank ( pour le test j'ai pris ça ), qui déclare un CityHandler etc etc..

    Seulement, il serait pratique que l'objet bank ( et tout autre building, d'ailleurs ), puisse appeler des méthodes de l'objet city qui le contient, or, c'est ce que je souhaitais faire avec le CityHandler, mais ça ne semble pas être une bonne idée.

    Donc, finalement, je me demande si c'est une erreur de conception fondamentale et s'il y a une autre solution pour faire ce que je veux faire ( voir éventuellement des schémas à suivre, qui permettent de faire ça efficacement. )

    Merci,

    Cordialement,

    MegaBigBoss

  2. #2
    Expert confirmé

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Par défaut
    retourne ton instance,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if (!isset(self::$instance)) {
        $c = __CLASS__;
        self::$instance = new $c;
    }
     
    return self::$instance;
    après y'a des chose plus simple a faire (et plus propre) deja tes classes sont style PHP 4, donc change les var en public et met bien les public devant tes méthodes,


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $c = __CLASS__;
    self::$instance = new $c;
    le __CLASS__ sert a rien fait direct new self
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $query_load = $db->prepare("SELECT id FROM city");
    $query_load->execute();
    la requete préparée sert a rien aussi, fait juste un query, utilise un FETCH_CLASS aussi ça sera beaucoup beaucoup plus simple

  3. #3
    Membre confirmé Avatar de MegaBigBoss
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    144
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 144
    Par défaut
    J'ai modifié ma fonction getInstance() de façon à ce qu'elle retourne l'instance, et j'ai mis mes variables au format PHP5, seulement, j'ai toujours le même problème d'appel infini.

    La fonction __construct() ne devrait-elle pas être appelée uniquement lorsque "new self" est crée, soit une seule fois, étant donné que c'est un singleton ?

    Voici la fonction modifiée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    	public static function getInstance() 
    	{
    		if(!isset(self::$instance)) 
    		{
    			self::$instance = new self;
                    }
    		return self::$instance;
    	}

  4. #4
    Expert confirmé

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Par défaut
    si, tu dois avoir au autre problème quelque part

  5. #5
    Membre confirmé Avatar de MegaBigBoss
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    144
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 144
    Par défaut
    Je pense que ça vient du fait que le cityHandler contient un objet city, qui contient un objet bank, qui essaye d'appeller le cityHandler::getInstance(), qui comme il n'a pas fini de se déclarer est considéré comme null et se redéclare peut être ?

    Est-ce possible ?

  6. #6
    Expert confirmé

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Par défaut
    Citation Envoyé par MegaBigBoss Voir le message
    Je pense que ça vient du fait que le cityHandler contient un objet city, qui contient un objet bank, qui essaye d'appeller le cityHandler::getInstance(), qui comme il n'a pas fini de se déclarer est considéré comme null et se redéclare peut être ?

    Est-ce possible ?
    non, montre tout ton code

Discussions similaires

  1. [8.5] conception tableau avec quadrillage
    Par kikidrome dans le forum SAP Crystal Reports
    Réponses: 24
    Dernier message: 20/06/2007, 16h58
  2. error LNK2001 avec singleton
    Par BadFox dans le forum C++
    Réponses: 9
    Dernier message: 09/12/2005, 13h55
  3. Réponses: 9
    Dernier message: 22/07/2005, 17h10
  4. [Conception] Queue avec priorité
    Par Mobius dans le forum Général Java
    Réponses: 4
    Dernier message: 11/04/2005, 09h26
  5. [Débutant][Conception] Erreur avec une classe interne
    Par Devil Redneck dans le forum Général Java
    Réponses: 5
    Dernier message: 11/06/2004, 16h45

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