Zend_Registry:现实生活中的例子

时间:2010-03-27 22:26:59

标签: php zend-framework global-variables

您觉得Zend_Registry有用吗?

应该使用哪些任务?不是吗?

变量的全球状态不是一个好习惯。 主要对象可以通过$front->setParam('paramName', $object)注入全局状态, 那么Zend_Registry的目的是什么?。

3 个答案:

答案 0 :(得分:10)

引用PoEAA on Registry Pattern

  

如果要查找对象,通常从另一个与其关联的对象开始,并使用该关联导航到该对象。因此,如果要查找客户的所有订单,请从客户对象开始,并使用方法获取订单。但是,在某些情况下,您将无法使用适当的对象。您可能知道客户的ID号但没有参考。在这种情况下,你需要某种查找方法 - 查找程序 - 但问题仍然存在:你如何找到查找器?

我使用注册表(当我使用它时)的主要原因是因为它创建了一个易于访问的应用程序范围。使用注册表,我不必在全球范围内丢弃对象;只有注册表本身是全球性的。从任何地方查找我扔进注册表的任何内容都很方便,包括模型:

  • Zend_Cache,Zend_Translate,重要的应用程序路径等

但是,就像单身人士一样,注册管理机构经常不受欢迎。这是一个article by Brandon Savage with some thought about why not to use the Registry。针对注册管理机构的主要论点是

  • 使单元测试更难
  • 没有经验的程序员可能会过多地投入其中并且不关心正确的设计

投票反对注册管理机构的人通常主张使用Dependency Injection,但应该注意的是,一旦你获得了它的实例,你也可以注入注册表。但是,您没有Inversion of Control,因为using对象将从Registry中提取它所需的内容。使用注册表作为服务定位器是一种有效的方法。

请参阅此article by Martin Fowler about ServiceLocator vs. Dependency Injection

正如您对问题的评论中指出的那样,Zend_Registry并非严格的单身人士。除了使用Zend_Registry::getInstance()获得的全局实例外,您还可以根据需要实例化多个实例。所以对象可以拥有自己的注册表。但是当以这种方式使用Registry时,它基本上只是一个美化的ArrayObject。

最后注意事项:就像所有设计模式一样,如果适用于您的问题,请使用它。

答案 1 :(得分:10)

当您使用$front->setParam时,您正在Front Controller中定义一个参数。

但该参数在(或不应使用)应用程序的其他层(例如Model)中不可用。

与任何其他全局变量一样,

Zend_Registry可以从应用程序的任何位置获得 - 包括模型内部。

但是使用注册表而不是一堆全局变量可以确保你不会在任何地方都有很多全局变量:即使使用注册表意味着一些全局状态(这不是那么好,应该说),最好将它们放在一个地方。


一些现实生活中的例子可能是:

  • 将连接存储到数据库,该数据库在bootsreap中建立,但在模型
  • 中使用
  • 全局存储适用于应用程序所有层的翻译/本地化的(或任何机制) - Zend Framework本身就是这样做的。


最后,我发现Zend_Registry有用吗?

嗯,当谈到拥有一些全球状态时,是的,它很有用。

但如果它的使用可以避免,它可能会更好:从概念上讲,不要让你的类依赖于任何全局状态更好:更容易重用,更容易测试,......
关于这一点,您可能想看看 Dependency Injection 是什么。

答案 2 :(得分:4)

我同意Pascal MARTIN。我刚刚开始习惯依赖注入。但我还没有找到一种方法在控制器中注入对象,所以我最近做的是使用de registry来访问控制器中的服务。在目前的项目中,我正在做以下事情:

自举:

// simple DI without an IoC container, and what have you
$dbAdapter    = Zend_Db::factory( /* bla bla */ );
$mediaService = new Service_Media( new Repository_Media_Db( $dbAdapter ) );
$registry     = Zend_Registry::getInstance();
$registry->mediaService = $mediaService;

...然后在控制器中:

public function init()
{
    $this->_mediaService = Zend_Registry::get( 'mediaService' );
}

public function listAction()
{
    // simplified
    $this->view->media = $this->_mediaService->listAllUploadedVideos();
}

希望这对你有用。