PHP维护类状态

时间:2012-09-07 16:34:00

标签: php

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

我最初是通过静态方法完成的,效果很好。但是,作为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,但这似乎不合适,除非我遗漏了什么。

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

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

5 个答案:

答案 0 :(得分:3)

我看起来你可以从使用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实例。但是,如果实例已存在,则需要返回该实例。

基本上,单身人士是其自身实例的看门人,并且它固执地拒绝让自身存在多个实例。

答案 1 :(得分:1)

听起来你想要做一个 Singleton 类。这将在一个类中创建一个实例,并允许您访问另一个类中的同一个实例。查看http://www.developertutorials.com/tutorials/php/php-singleton-design-pattern-050729-1050/了解详情。

答案 2 :(得分:1)

如何让它成为单身人士课程?

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

答案 3 :(得分:0)

您需要的是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();

答案 4 :(得分:0)

听起来有点像你想要单身,虽然as an anti-pattern我会避免它。

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

您需要的最佳案例可能是您正在构建的普通(非静态)类,然后从全局访问...不是超级整洁,但允许构造/破坏和成员,以及您的静态使用$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(..);