ZF-11420: Zend_Session doesn't allow you to destory and recreate a session

Description

My requirement is, When user agent change session should destroy, and it should start new session. But Zend_Session::start() is throwing an exception if destroy was called before start().

 
try {
  Zend_Session::start();
} catch (Zend_Session_Exception $e) {
  Zend_Session::destroy(true);
  Zend_Session::start(); // breaking here
  Zend_Session::regenerateId();
}
Zend_Session::registerValidator(new Zend_Session_Validator_HttpUserAgent());

Exception:

Uncaught exception 'Zend_Session_Exception' with message 'The session was explicitly destroyed during this request, attempting to re-start is not allowed.' in library\Zend\Session.php:431

Comments

I have a global session management in bootstrap, which validates the request and starts session. By that time, request won't be dispatched. Then why to make another request to redirect to another page? As we already knew that session is wrong one? we could easily start new one right?

As I understood, The reason is the second start() command is silently ignored if it was already called in that request.

IMPORTANT!

{{session_destroy()}} will (by design) prevent any further session cookies to be sent. This means your use case must be avoided if you are using cookies.

Here is more info in php manual comments: http://php.net/manual/en/…

Here are my analysis on the issue: http://framework.zend.com/issues/browse/…

You don't need to destroy session in order to regenerate id. That is a wrong understanding of how sessions work.

Here is how you clear a session with ZF:


// assuming sessionData is the namespace you're using
$sessionData->unsetAll();

The above will result in all data in the namespace to be unset and this change will be saved in your session storage.

This is how you change session ID by sending a different cookie to browser:


Zend_Session::regenerateId();

This will result in generating a new session id and sending a new session cookie to the browser. The old session id (old cookie) becomes invalid after this function call.

Here is a fixed version of your source code:


Zend_Session::registerValidator(new Zend_Session_Validator_HttpUserAgent());

try {
  Zend_Session::start();
} catch (Zend_Session_Exception $e) {

  // clear all data in all namespaces
  foreach(Zend_Session::getIterator() as $name=>$ns){
    Zend_Session::namespaceUnset($name); 
  }

  // alternatively   $_SESSION = array()
  
  // generate new session id and send new cookie to browser
  Zend_Session::regenerateId();
}

It is an expected behavior as Zend_Session wraps around php built-in session support. By PHP's design, after destroying a session it must not be started again.

http://php.net/manual/en/…