我正试图找到一种将所有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');
或者有其他方法可以让应用程序中的任何地方都可以访问数据吗?
谢谢!
您所谈论的是注册表模式(以及另一篇关于它的好文章)。虽然它有一些缺点(例如,为了测试从注册表中获取一些数据的方法,我们还必须模拟这个注册表),但它肯定比使用全局变量或Singleton要好。
事实上,在Zend Framework 1中,这个模式是完全按照字面意思实现的:
// 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
是什么?它是一个物体吗?还是数组?或者其他野兽,比如功能或资源?你必须依赖这里的注释,这通常不是一件好事——除非你处理的是琐碎而常见的对象(比如查询参数或数据库资源对象)。
对于这种性质的东西,对静态类进行硬编码引用的问题在于,您正在创建对这些静态类的紧密依赖。如果您决定在将来更改"全局"属性的源,那么您的应用程序中就会充斥着对该源的引用。
如果你想要一个有点全局性的属性实体,一个更好的方法是创建一些你将实例化的东西,并提供一个适合你的应用程序需要的接口。为了便于讨论,让我们调用这个接口GlobalConfigurationProvider
。然后,您的应用程序代码可能期望(并依赖)GlobalConfigurationProvider
的一些实现。现在,如果您将来更改实现配置的方式,您只需要担心新元素——GlobalConfigurationProvider
的新实例,而不必担心引用配置提供程序的所有类、视图等。
不要使用全局容器类,而是考虑编程OO,并将方法和变量放在一个类中。
在您的错误示例中,错误属于一个类,应该保留在那里。
对类的引用可以由全局注册表保存,或者更好的是,由IoC容器保存。