2009-02-15 9 views
5

J'ai une classe pour interagir avec un serveur memcache. J'ai différentes fonctions pour insérer, supprimer et récupérer des données. A l'origine chaque fonction fait appel à memcache_connect(), mais qui était inutile, par exemple .:Partager des variables entre des fonctions en PHP sans utiliser de globales

mc->insert() 
mc->get() 
mc->delete() 

ferait trois connexions memcache. Je CONTOURNÉS en créant une construction pour la classe:

function __construct() { 
    $this->mem = memcache_connect(...); 
} 

puis en utilisant $this->mem chaque fois que la ressource était nécessaire, pour chacune des trois fonctions utilisent la même ressource memcache_connect.

Ceci est bien, si j'appelle la classe à l'intérieur d'autres classes, par exemple .:

class abc 
{ 
    function __construct() { 
     $this->mc = new cache_class; 
    } 
}  
class def 
{ 
    function __construct() { 
     $this->mc = new cache_class; 
    } 
} 

alors il continue à faire deux appels memcache_connect, quand il seulement besoins un.

Je peux le faire avec des globals mais je préférerais ne pas les utiliser si je n'ai pas à le faire.

Exemple GLOBALS mise en œuvre:

$resource = memcache_connect(...); 

class cache_class 
{ 
    function insert() { 
     global $resource; 
     memcache_set($resource , ...); 
    } 
    function get() { 
     global $resource; 
     return memcache_get($resource , ...); 
    } 

} 

Alors, peu importe combien de fois la classe est appelée il n'y aura qu'un seul appel à memcache_connect.

Existe-t-il un moyen de le faire ou devrais-je simplement utiliser globals?

Répondre

9

Je coderez une autre classe en utilisant un singleton pour obtenir la seule instance de memcache. Comme cela -

class MemCache 
{ 
    private static $instance = false; 
    private function __construct() {} 

    public static function getInstance() 
    { 
    if(self::$instance === false) 
    { 
     self::$instance = memcache_connect(); 
    } 

    return self::$instance; 
    } 
} 

et utilisation -

$mc = MemCache::getInstance(); 
memcache_get($mc, ...) 
... 
+0

C'est une solution raisonnable mais soyons réalistes, c'est un global. :) – cletus

+0

C'est ce que je ferais. Vous ne pouvez pas le tester, mais soyons honnêtes, qui teste ce genre de chose de toute façon? –

+0

La question est de savoir comment testable reste le reste du code entier si une petite partie n'est pas testable. Ou comment implémenteriez-vous un objet MemCache simulé pour d'autres tests? – okoman

5

Pass en l'instance MC:

class abc 
{ 
    function __construct($mc) { 
     $this->mc = $mc; 
    } 
}  
class def 
{ 
    function __construct($mc) { 
     $this->mc = $mc; 
    } 
} 

$mc = new cache_class; 
$abc = new abc($mc); 

etc.

2

Je pense que vous êtes à la recherche de propriétés statiques ici.

class mc { 
    private static $instance; 

    public static function getInstance() { 
     if (self::$instance== null) { 
      self::$instance= new self; 
     } 
     return self::$instance; 
    } 

    private function __construct() { 
     $this->mem = memcache_connect(...); 
    } 
} 

Ceci implémente un motif singleton de base. Au lieu de construire l'objet appel mc::getInstance(). Jetez un oeil à singletons.

+0

Drôle comment les gens votent après avoir lu pas plus que la première phrase d'une réponse. +1 à nouveau. – Tomalak

1

Vous devez utiliser l'injection de dépendance. Le modèle singleton et les constructions statiques sont considérés comme une mauvaise pratique parce qu'ils sont essentiellement globaux (et pour une bonne raison - ils vous obligent à utiliser n'importe quelle classe instanciée par opposition à une autre).

Voici quelque chose comme ce que vous devriez faire pour avoir un entretien facile.

class MemCache { 
    protected $memcache; 

    public function __construct(){ 
     $this->memcache = memcache_connect(); 
    } 
} 

class Client { 
    protected $MemCache; 

    public function __construct(MemCache $MemCache){ 
     $this->MemCache = $MemCache; 
    } 

    public function getMemCache(){ 
     return $this->MemCache; 
    } 
} 

$MemCache = new MemCache(); 
$Client = new Client($MemCache); 
$MemCache1 = $Client->getMemCache(); 

// $MemCache and $MemCache1 are the same object. 
// memcache_connect() has not been called more than once. 
Questions connexes