ZF-5619: ::assertRedirectTo does not work as expected

Description

The assertRedirectTo does not work as expected.

Cases:


public function indexAction(){
     $this->_helper->redirector('login');
}

public function indexAction(){
     if( !$this->_request->isPost() ){
          $this->_helper->redirector('login');
     }
     
     // Do other stuff
}

public function indexAction(){
     if( !$this->_request->isPost() ){
          $this->_helper->redirector('identify');
     }
     
     // Do other stuff

     if( $this->_request->getPost('user_id') ){
           $this->_helper->redirector('login');
     } else{
            $this->_helper->redirector('logout');
     }

}

In the last case the redirection in the browser goes well, but in the unittest it validates with the last redirection. When return null; is put below the redirector, the problem is resolved, but it doesn't look like a good solution.

Also the redirectAndExit function causes the unittest to crash.

EDIT

Why can't I find a @# reply button!!

@below: That does resolve the issue. But it's weird that the first redirect does work as expected and with testing it doesn't. I think this should be more clear in the documentation. I can imagine that more people will have problems with this. It's stated in the docs, but not explicitly. (Some examples uses the return).

Comments

The primary issue I'm seeing right now is actually in your code. When you call _forward() or one of the _redirect() or redirector methods, you should always return immediately; if you do not do so, the action continues to execute, which can lead to the problems you're describing.

Can you do the following: in each place above where you call $this->_helper->redirector(), change the call to:


return $this->_helper->redirector(...);

and let me know if that corrects the issue.

I can confirm this bug. You can reproduce it by calling Zend_Controller_Action_Helper_Redirector::setUseAbsoluteUri(true). Then perform redirect and check for the redirect.

By the way, HTTP standard requires use of absolute URL for redirect (in location header).

I can also confirm this unexpected behaviour in my unit tests. Consider the following controller and test ...


class AccountController extends Zend_Controller_Action
{
    /** @var Application_Model_Account */
    protected $_account;

    public function init()
    {
        // may redirect, thus placed at the beginning ...
        $id = $this->_getId();

        $account = new Application_Model_Account();
        $this->_getAccountMapper()->find($id, $account);

        ...

        $this->_account = $account;
    }

    protected function _getId()
    {
        $request = $this->getRequest();
        if (($id = $request->getParam('id', null)) === null) {
            $this->_helper->redirector('index', 'index');
        }
        return (int) $id;
    }
}


class AccountControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{
    ...

    public function testIndexActionShouldRedirectIfAccountIdNotGiven()
    {
        $this->dispatch('/account');
        $this->assertRedirectTo('/'); // FAILS
    }
}

I overlooked Metthew's comment ...

bq. Can you do the following: in each place above where you call $this->_helper->redirector(), change the call to:

 and let me know if that corrects the issue.

This fix the problem. The new AccountController looks like this ...

public function init() { $id = $this->_request->getParam('id', null);

$mapper = Application_Model_Mapper::factory('Account');
$this->_account = $mapper->find($id);

}

public function indexAction() { if (!$this->_account instanceof Application_Model_Account || $this->_account->id === null) { $this->_helper->flashMessenger( new Application_Model_FlashError('Account does not exist')); return $this->_helper->redirector('index', 'index'); }

// ...

} ```

I think this issue can be resolved as not an issue. The documentation has been updated in ZF-7455.