拥有保存全局数据的容器类是个好主意吗?

时间:2012-09-13 19:51:27

标签: php oop model-view-controller

我正试图找到一种方法将所有php应用程序数据保存在一个地方。 例如,获取和发布参数,页面标题,分页结果等,以避免使用全局变量。

在以下对象中保持控制器之间的所有数据和交换是一个好主意吗?

class container {

protected static $_instance;
protected $_instance_class;

public static function instance($instance_name = 'default')
{
    $c = __CLASS__;

    if ( ! isset($c::$_instance[$instance_name]))
    {
        $c::$_instance[$instance_name] = new $c();
        $c::$_instance[$instance_name]->_instance_class = $instance_name;
    }
    return $c::$_instance[$instance_name];
}

public function set($key, $val)
{
    // someting like $this->$key = $val;
}

public function get($key)
{
    // someting like retrun $this->$key;
}

}

然后,例如在模型中

container::instance('messages')->set('error', 'some error');

并在控制器或视图中

container::instance('messages')->get('error');

或者还有其他方法可以让应用程序中的任何地方都可以访问数据吗?

谢谢!

3 个答案:

答案 0 :(得分:1)

您所谈论的内容称为Registry pattern(以及其他good article)。虽然它有一些缺点(例如,测试从Registry中获取一些数据的方法,我们也必须模拟这个注册表),但它肯定比使用全局变量或单例更好。

事实上,在Zend Framework 1中,这种模式已经实现quite literally

// setting a value (usually done in Bootstrap)
Zend_Registry::set('index', $value);

// getting a value (usually in actions and/or models)
$value = Zend_Registry::get('index');

为了说明这种方法可能出现的问题,让我们分析以下内容:

class FooController extends Zend_Controller_Action {
    public function barAction() {
        $baz = Zend_Registry::get('baz');
        $model = new Some_Model($baz); 
        ...
    }
}

问题很简单:$baz这里有什么东西?它是一个对象吗?还是阵列?还是其他一些野兽,比如功能或资源?你必须依赖于这里的评论,这通常不是一件好事 - 除非你正在使用普通对象(如查询参数或数据库资源对象)。

答案 1 :(得分:0)

对于这种性质的东西,对静态类进行硬编码引用的问题是你正在创建对这些静态类的紧密依赖。如果您决定在将来更改“全局”属性的来源,那么您的应用程序就会散布着对该源的引用。

如果你想要一个有点全局的属性实体,一个更好的方法是创建一些你将实例化的东西,并提供一个定制你的应用程序需要的接口。为了论证,让我们调用这个接口GlobalConfigurationProvider。然后,您的应用程序代码可以期望(并依赖于)GlobalConfigurationProvider的某些实现。现在,如果您改变将来实现配置的方式,您只需要担心新元素 - GlobalConfigurationProvider的新实例,而不是您引用的所有类,视图等。配置提供商。

答案 2 :(得分:0)

不要使用全局容器类,而应考虑编写OO并将方法和变量保存在一个类中。

在您的错误示例中,错误属于某个类,应该保留在那里。

您的课程的引用可以由全局注册表持有,或者更好,由IoC容器持有。