【问题标题】:Share variables between functions in PHP without using globals在 PHP 中的函数之间共享变量而不使用全局变量
【发布时间】:2009-02-15 11:33:57
【问题描述】:

我有一个与内存缓存服务器交互的类。我有不同的功能来插入、删除和检索数据。最初每个函数都调用了memcache_connect(),但这是不必要的,例如:

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

将建立三个 memcache 连接。我通过为该类创建一个构造来解决此问题:

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

然后在需要资源的地方使用$this->mem,因此三个函数中的每一个都使用相同的memcache_connect 资源。

这没关系,但是如果我在其他类中调用该类,例如:

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

那么它仍然会发出两个memcache_connect 调用,而它只需要一个

我可以使用全局变量来做到这一点,但如果没有必要,我宁愿不使用它们。

全局变量实现示例:

$resource = memcache_connect( ... );

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

}

那么无论类调用多少次,都只会调用一次memcache_connect

有没有办法做到这一点,还是我应该只使用全局变量?

【问题讨论】:

    标签: php oop global


    【解决方案1】:

    我会使用单例模式编写另一个类来获取内存缓存的唯一实例。像这样-

    class MemCache 
    { 
      private static $instance = false;   
      private function __construct() {}
    
      public static function getInstance()
      { 
        if(self::$instance === false)
        { 
          self::$instance = memcache_connect(); 
        } 
    
        return self::$instance; 
      } 
    }
    

    和用法-

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

    【讨论】:

    • 这是一个合理的解决方案,但让我们面对现实吧,它是一个全球性的解决方案。 :)
    • 这就是我要做的。你不能测试它,但老实说,这种东西到底是谁测试的?
    • 问题是,如果一小部分不可测试,整个代码的其余部分如何保持可测试性。或者你将如何为其他测试实现一个模拟的 MemCache 对象?
    • @cletus:它使用全局模式,但没有使用全局范围。程序在环境中运行;在该级别的组织中,一切都是全局的,即使您在类属性中拥有所有真实数据。您希望避免在全局中使用变量,但外部数据源的接口必须存在于某个地方,并且无论如何您都希望使用 Singleton。
    【解决方案2】:

    传入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);
    

    等等

    【讨论】:

      【解决方案3】:

      我认为您正在这里寻找静态属性。

      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(...);
          }
      }
      

      这实现了一个基本的单例模式。而不是构造对象调用mc::getInstance()。看看singletons

      【讨论】:

      • 有趣的是,人们在阅读完答案的第一句话后如何投票。再次 +1。
      【解决方案4】:

      你应该使用依赖注入。单例模式和静态结构被认为是不好的做法,因为它们本质上是全局的(并且有充分的理由——它们使您能够使用您实例化的任何类而不是其他类)。

      为了便于维护,您应该执行以下操作。

      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.
      

      【讨论】:

        猜你喜欢
        • 2012-12-14
        • 1970-01-01
        • 2019-08-17
        • 2013-03-22
        • 2013-12-09
        • 1970-01-01
        • 1970-01-01
        • 2016-03-25
        • 2017-11-19
        相关资源
        最近更新 更多