PHP维护类状态


PHP maintain class state

我想要一个库类来维护同一请求的状态。我的用例是,我想将"消息"传递给类,然后随时从视图调用它们。可以从应用程序的任何部分添加消息。

我最初是通过静态方法完成的,效果很好。但是,作为lib的一部分,我还需要调用__construct__destruct(),这在静态类上是无法完成的。

这里有一个非常简单的例子,我正在尝试做什么:

class Messages
{
  private static $messages = array();
  public function __construct()
  {
    // do something
  }
  public function __destruct()
  {
    // do something else
  }
  public static function add($message)
  {
    self::$messages[] = $message;
  }
  public static function get()
  {
    return self::$messages;
  }
}

然后,我可以通过在代码中的任何位置添加消息

Messages::add('a new message');

如果可能的话,我希望避免使用静态(可测试性)。我看过DI,但它似乎不合适,除非我遗漏了什么。

我可以创建一个类(非静态),但我如何确保所有消息都写入同一个对象,以便以后可以检索所有消息?

解决这个问题的最佳方法是什么?

我认为您可以从使用Singleton模式中受益——它是为一个在整个请求中必须只有一个实例的对象设计的。基本上,您可以创建一个私有构造函数和一个静态方法来检索唯一的实例。下面是一个单例的例子,它将执行您所描述的操作。

<?php
class Messages
{
    private static $_instance;
    private $_messages = array();
    private function __construct() {
        // Initialize
    }
    static public function instance() {
        if (! self::$_instance) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
    public function add_message( $msg ) {
        $this->_messages[] = $message;
    }
    public function get_messages() {
        return $this->_messages;
    }
    private function __destruct() {
        // Tear-down
    }
}
$my_messages = Messages::instance();
$my_messages->add_message( 'How now, brown cow?' );
// ...
$your_messages = Messages::instance();
$msgs = $your_messages->get_messages();
echo $your_messages[0]; // Prints, "How now, brown cow?"

由于构造函数是私有的,因此只能从对象本身的方法中创建Messages对象。由于您有一个静态方法instance(),因此可以从中创建一个新的Messages实例。但是,如果实例已经存在,则需要返回该实例。

基本上,单例是它自己实例的看门人,它顽固地拒绝让自己的多个实例存在。

听起来你想上一堂Singleton课。这将在一个类中创建一个实例,并允许您访问另一个类的同一实例。退房http://www.developertutorials.com/tutorials/php/php-singleton-design-pattern-050729-1050/了解更多信息。

让它成为一个单例类怎么样?

class Messages
{
    // singleton instance of Messages
    private static $instance;
    public function __construct() { ... }
    public static function getInstance()
    {
        if (!self::$instance)
        {
            self::$instance = new Messages();
        }
        return self::$instance;
    }
}

这将确保所有消息都写入同一个对象,还允许您调用__construct__destruct

您需要的是Singleton模式:

final class Singleton {
    // static variable to store the instance
    private static $instance = NULL;
    // disable normal class constructing
    private function __construct() {}
    // instead of using the normal way to construct the class you'll use this method
    public static function getInstance() {
       if (NULL === self::$instance) {
           self::$instance = new self;
       }
       return self::$instance;
    }
    // disable external cloning of the object
    private function __clone() {}
}
// get the instance across some of your scripts
$singleton = Singleton::getInstance();

听起来有点像你想要一个singleton,尽管作为一种反模式,我会避免它。

您可以创建一个完整的静态类,其中每个静态成员都调用一个self::_isBuilt();方法来构造元素。破坏有点棘手。

对于您的需求,最好的情况可能是立即构建一个普通(非静态)类,然后从全局。。。不是非常整洁,但允许构造/析构函数和成员,以及您的statics使用$this,这可能会有所帮助。如果你不喜欢全局变量,你也可以把它包装在一个方法中(JS中使用了一个技巧),但它并不整洁。

作为一个正常的全局类:

$myClass=new myClass();
//Access anywhere as:
globals['myClass']->myFunction(..);

包装在函数中

function my_class() {
 static $var=null;
 if ($var===null) $var=new myClass();
 return $var;
}
//Access anywhere as:
my_class()->myFunction(..);