Zend_Test&用于ACL的控制器插件(重定向)

时间:2011-01-02 04:56:24

标签: zend-framework zend-acl zend-controller-plugin

我怀疑在Zend Test中使用控制器插件重定向时出现问题?

我有一个像http://pastie.org/1422639这样的控制器插件我已经把echo语句用于调试。如果用户未登录,我有重定向登录的代码

if (!$auth->hasIdentity()) {
  echo 'no id, ';
  // redirect to login page
  $req->setDispatched(true);
  $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');echo 'got redir, ';
  $redirector->gotoUrl('/auth/login?returnUrl=' . urlencode($req->getRequestUri()));echo 'redirecting, ';
} ...

我发现在单元测试时,例如

$this->dispatch('/projects');

我得到的输出是

  

项目(确定我请求了项目页面/控制器),没有id(确定,我没有登录),得到redir(我让重定向器正常),重定向(它似乎重定向好了......),错误(但我得到了错误控制器)没有资源,

我到达错误控制器的原因似乎是我仍然进入了项目/索引页面。在索引操作中,我假设用户已登录。但是当它尝试获取登录用户时

$user = \Zend_Auth::getInstance()->getIdentity();

失败了......

如何在Zend Test中使用重定向器?或者它可能不是重定向器的问题?

1 个答案:

答案 0 :(得分:3)

这是一个由两部分组成的问题。首先,重定向器在重定向后默认调用PHP的exit,这会导致Zend_Test停止执行。在测试中,您必须配置重定向器不要这样做。像这样:

$redirector = new Zend_Controller_Action_Helper_Redirector();
if (APPLICATION_ENV == 'testing') {
    $redirector->setExit(false);
}
$redirector->gotoUrl("/blah/blah");

但是控制器插件中的问题是在使用重定向器之后,无法阻止Zend Framework进入调度循环并尝试执行动作方法。我已经阅读了各种形式的帖子(不记得在哪里随便),这是开发人员计划解决的Zend Framework中的一个已知问题。现在,我通过在我的错误控制器中添加这样的方法来解决这个问题:

public function pluginRedirectorAction() {
    $this->_helper->layout()->disableLayout();
    $this->_helper->viewRenderer->setNoRender();

    $code = $this->_getParam('code');
    $uri = $this->_getParam('uri');

    if (APPLICATION_ENV == 'testing') {
        $this->_helper->redirector->setExit(false);
    }
    $this->_helper->redirector->setCode($code);
    $this->_helper->redirector->gotoUrl($uri);
}

然后在我的控制器插件中,我有一个自定义方法来调用重定向:

protected function redirect($code, $uri) {
    $redirector = new Zend_Controller_Action_Helper_Redirector();

    if (APPLICATION_ENV == 'testing') {
        $request = $this->getRequest();
        $request->setModuleName('default');
        $request->setControllerName('error');
        $request->setActionName('plugin-redirector');
        $request->setParam('code', $code);  
        $request->setParam('uri', $uri);

        $redirector->setExit(false);
    }

    $redirector->setCode($code);
    $redirector->gotoUrl($uri);
}

通过执行此操作,您可以将实际调用重定向器移动到应用程序的控制器层,这样可以使单元测试正常工作(也就是$this->assertRedirectTo('/blah/blah');。)这会将请求修改为指向{{1上面显示的错误控制器中的方法。控制器插件中的重定向现在称为:

pluginRedirectorAction()

但它不会在return $this->redirect(307, '/somewhere/else'); 方法中起作用,因为ZF会在此之后立即启动路由器,这将覆盖routeStartup()方法指定的请求参数。您必须重新设计插件的管道,以便从redirect()调用重定向或者在调度周期后期调用的其他方法。 (我只在routeShutdown()内进行了测试。)