是否可以使用动作帮助器不仅适用于控制器?

时间:2012-03-27 16:13:36

标签: zend-framework session architecture

我正在寻找在zf应用程序中使用会话的最佳方法。 起初我做了类似的事情 - 在控制器超类的 init 方法中我初始化了会话:

class Vovkin_Controller_Action extends Zend_Controller_Action
{
    protected $_session;

    public function init()
    {   
        // here I define namespace 
        // ...
        $this->_session = new Zend_Session_Namespace($nameSpace);
        parent::init();
    }
    ...
}

在控制器中的会话之后以这种方式使用:

public function someAction()
{
    $this->_session->user = $user;
}

但我发现这种方法对于系统的其他部分(如插件,服务等)不是很方便,因为我必须以其他方式初始化会话,但我希望将其保存在一个地方,如果可能的话。所以我决定将其改为这种方法https://stackoverflow.com/a/2506447

现在我有一些动作帮助器来为具有不同命名空间的会话提供访问权限,它的工作原理如下:

public function someAction()
{
    $this->_helper->session()->user = $user;
}

到目前为止它看起来很有用,因为我可以通过这种方式访问​​系统其他部分的会话命名空间,例如在服务中:

class Vovkin_Model_Service_UserLoginService
{
    public function login()
    {
        $session = Zend_Controller_Action_HelperBroker::getStaticHelper('session')->direct();
        ...
    }   
    ....
}

但从架构和使用的资源角度来看,以这种方式使用它有多正确?

感谢。

1 个答案:

答案 0 :(得分:2)

您所评论的答案来自Zend Framework的主要贡献者之一Rob Allen,所以它在某种程度上是正确的。您可以在控制器上使用动作帮助器而不会出现任何问题。

但除此之外,这是完全错误的。服务与动作帮助器和前端控制器没有任何关系。你不能依赖它(对行动助手的服务)。

因此,由于应用程序引导程序作为初始化应用程序的容器,因此从那里获取必要的值是合理的。我建议你做的第一件事是使用Zend_Registry。但据我告诉你,它会再次初始化会话对象,因为它不会被擦除,它只是一个引用本地$_SESSION超全局的对象。所以,只需致电

new Zend_Session_Namespace($nameSpace)

但同样,这是错误的。您不应该让您的服务知道如何处理会话(从而在其中创建对象):

$session = Zend_Controller_Action_HelperBroker::getStaticHelper('session')->direct()

甚至

$session = Zend_Registry('userSession')

$session = new Zend_Session_Namespace('userSession')

因此你根本就没有使用bootstrap容器。相反,您应该提供一个通用接口来处理会话(可能是$ _SESSION甚至数据库),并将其作为参数(例如__construct($session))注入服务。但这是一个全新的主题(依赖注入)。

所以,你有两个选择考虑ZendFramework 1.11的当前状态(已经陈旧且充满了不良做法):

1)您将通过控制器使用服务:

因此,您将通过操作助手获取会话,然后将其作为参数传递给您的服务。

new Vovkin_Model_Service_UserLoginService($session)

2)您将独立于控​​制器使用服务,并通过引导容器获取依赖关系:

嗯,最糟糕的是要获得引导程序,你需要有一个frontController依赖项。

$bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');

所以,避免它,并使用第一个选项,而是注入依赖项。虽然,如果您真的想要这样,请直接访问它:

$bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');
$bootstrap->get('userSession')
可悲的是,最后,这一切都是错的。但这是你用ZF 1做的最好的。你应该期待ZF 2和Symfony 2更好地理解这些概念。

这是一个很好的解释:http://symfony.com/doc/current/book/service_container.html (我知道你使用的是ZF,但没关系,概念是关键)