I’m looking for best way of using session within zf application.
At first I did something like this – in init method of controller superclass I initialized session:
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();
}
...
}
after that session in controller was used in this way:
public function someAction()
{
$this->_session->user = $user;
}
but I found this approach not very handy for other parts of system, like plugins, services, etc, because there I had to init session in other way, but I want keep it in one place if it’s possible. So I decided to change it to this approach https://stackoverflow.com/a/2506447.
Now I have a few action helpers to provide access for sessions with different namespaces, it works like this:
public function someAction()
{
$this->_helper->session()->user = $user;
}
and so far it looks useful, because I can get access to session namespaces in other parts of system, for example in services, in this way:
class Vovkin_Model_Service_UserLoginService
{
public function login()
{
$session = Zend_Controller_Action_HelperBroker::getStaticHelper('session')->direct();
...
}
....
}
but how much it’s correct to use it in this way, from point of architecture and used resources?
Thanks.
The answer you have refereed to is from Rob Allen, one of the main contributors of Zend Framework, so it’s right to some extent. You can go with the action helpers on controllers without any problems.
But outside it, it’s completely wrong. Services doesn’t has nothing with action helpers and the front controller. You can’t put a dependency on it (services to action helpers).
So, as the application bootstrap works as a container for initializing the application, it’s reasonable to get the necessary values from there. The first thing I would suggest you is to use
Zend_Registry. But as far as I cal tell you, it would be the same initializing the session object again, since it will not be wiped, it’s just an object referencing the native$_SESSIONsuperglobals. So, simply callnew Zend_Session_Namespace($nameSpace).But again, this is wrong. You should not let your services know how sessions are handled (thus creating the objects inside it):
or even
$session = Zend_Registry('userSession')or
$session = new Zend_Session_Namespace('userSession')With that you are also not using the bootstrap container at all. Instead you should provide a common interface to deal with sessions (it could be $_SESSION or even a database) and inject it into the service as a parameter (e.g.
__construct($session)). But that’s a whole new subject (Dependency Injection).So, you have two options considering the current state of the ZendFramework 1.11 (that’s already old and full of bad practices):
1) You’ll use services through controllers:
So you will get the session through the action helper and then pass it as a parameter to your service.
2) You will use services independently of controllers and will get the dependencies through the bootstrap container:
Well, the worst thing is that to get the bootstrap you need to have a frontController dependency.
So, avoid it, and go with the first option, injecting the dependency instead. Although, if you really want it in that way, access it directly:
Sadly, in the end, it’s everything wrong. But it’s the best you can do with ZF 1. You should look forward to ZF 2 and Symfony 2 to better understand these concepts.
Here it’s a good explanation: http://symfony.com/doc/current/book/service_container.html
(I know that you’re using ZF, but it doesn’t matter, the concept is the key)