Zend_Session : Clean $_SESSION before calling start
Let's say a web application store an object of class My_Object in the php session, under the name 'myobject'. When I open another php application where this class doesn't exist, Zend_Session::start() throw an exception when attempting to unserialize My_Object.
Thus, I need to clean the $_S开发者_运维百科ESSION variable to get rid of 'myobject'. But to clean $_SESSION variable, I first need to call session_start() and once it has been called, Zend_Session::start() throws the following exception :
Uncaught exception 'Zend_Session_Exception' with message 'session has already been started by session.auto-start or session_start()'
This is thrown even if I class session_destroy() before calling Zend_Session::start().
Can anyone help me on this ?
Thanks by advance,
Eric.
EDIT : To add clarification, here is the function I call on my controller initializer plugin :
protected function _initSession() {
try {
session_start();
unset($_SESSION['myobject']);
session_destroy();
Zend_Session::start(); // throws an exception !!!
}
catch (Exception $e) {
echo $e; exit;
}
}
EDIT 2 :
To add further clarification, here is the exception thrown by Zend_Session::start() when it encounters an unknown class :
Warning: include_once(My/Object.php): failed to open stream: No such file or directory in /usr/local/zend/share/ZendFramework/library/Zend/Loader.php on line 146
Now that I've written this, I wonder if I sould start the session before instanciating the Zend autoloader...
What version of Zend Framework are you using?
The reference manual states this:
Using Sessions with Objects
If you plan to persist objects in the PHP session, know that they will be » serialized for storage. Thus, any object persisted with the PHP session must be unserialized upon retrieval from storage. The implication is that the developer must ensure that the classes for the persisted objects must have been defined before the object is unserialized from session storage. If an unserialized object's class is not defined, then it becomes an instance of stdClass.
It sounds like one possible workaround would be to include the source file for the object that is serialized in the session, so it doesn't encounter that error. But it also states that if the class is not defined, it becomes an instance of stdClass, so since that is not the behavior you are seeing, it seems like a bug or you may be using an older version.
OK, sorry for to answer my own question but it looks like I misunderstood the exception thrown by Zend_Session. The problem actually came from Zend_Loader and not the underlying PHP session. The fact was that I was instanciating Zend autoloader in index.php, which is not a good idea since from the moment it is instanciated, Zend_Loader will try to autoload every class that has not been explicitly included [EDIT : To be clearer, it will try to instanciate every class whode name begins by one of the namespaces registered - and in my code, I had the namespace "My_" registered with the zend loader...]
The solution is pretty simple : instanciate Zend_Loader after Zend:Session::start(). I just put the initialization of Zend_Loader in my bootstrap, after Zend_Session::start() and everything works flawlessly : My_Object class is unserialized by Zend_Session::start() as stdClass (thanks to drew010 for pointing me in the right direction); which is what is excepted.
Thanks for your help, guys.
By the sounds of the error, it doesn't sound like the object is the problem, but the way that you are starting the session is.
"Uncaught exception 'Zend_Session_Exception' with message 'session has already been started by session.auto-start or session_start();"
protected function _initSession() {
try {
**session_start();**
unset($_SESSION['myobject']);
session_destroy();
**Zend_Session::start();** // throws an exception !!!
}
catch (Exception $e) {
echo $e; exit;
}
}
In this code you ARE invoking the session_start()
, and THEN using the Zend_Session::start()
.
This insinuates that the Zend session throws an exception if sessions have already been invoked previously.
You could just catch the Exception and just choose to do nothing with it?
protected function _initSession() {
try {
session_start();
unset($_SESSION['myobject']);
session_destroy();
Zend_Session::start(); // throws an exception !!!
}
catch (Exception $e) {
echo $e; exit;
}
catch (Zend_Session_Exception $zendException)
{
// Do nothing, ignore exception
}
}
精彩评论