I have implemented a logic in application module's bootstrap which will redirect users to login page if they are not signed. I have
class Module
{
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$session = new Container('signin');
if (!isset($session->member)){
$eventManager->attach(MvcEvent::EVENT_ROUTE, array($this,'routeMatched'), -100);
}
}
public function routeMatched(MvcEvent $e)
{
$match = $e->getRouteMatch();
// No route match, this is a 404
if (!$match instanceof RouteMatch) {
return;
}
$list = array('login', 'signin', 'upload');
// Route is whitelisted
$name = $match->getMatchedRouteName();
if (in_array($name, $list)) {
return;
}
// Redirect to the user login page, as an example
$router = $e->getRouter();
$url = $router->assemble(array(), array(
'name' => 'signin'
));
$response = $e->getResponse();
$response->getHeaders()->addHeaderLine('Location', $url);
$response->setStatusCode(302);
return $response;
}
}
As you can see below code inside onBootstrap
will check if the session container doesn't have member
variable set or not, if it is not set then the EVENT_ROUTE is attached which internally handles what to do depending on whether current route is a white listed or not.
$session = new Container('signin');
if (!isset($session->member)) ...
The problem here is that $session->member
is always getting null
. I am assigning this variable in the login action inside my controller like this
if ($data->authenticate($member->email, $member->password)){
$session = new Container('signin');
$session->member = $member;
return $this->redirect()->toRoute('member-control-panel');
}else{
$view->setVariable('error', 'Could not verify user/password');
}
What is the problem here?
Update:
I made the modifications as suggested by Wilts in his answer. It still did not work but I modified the code slightly to store the scalar value (email) instead of object (member). Now it is working so the question is why session container is not storing object but only scalar variables?
In my signin action I made changes like this
$session = new Container('signin');
//$session->member = $member; //removed
$session->email= $member->email; //New
In the bootstrap like this
$session = new Container('signin');
if (!isset($session->email)){
$eventManager->attach(MvcEvent::EVENT_ROUTE, array($this,'routeMatched'), -100);
}
Handling sessions correctly involves much more then simply dumping your variables into a Container
instance. A session cannot store objects without serializing them. It means you have to deserialize them again when resolving them from session.
To help you with managing your session storage ZF2 has a SessionManager
class I suggest you create a SessionManager
to get control over your session variables. You can read more in the the official ZF2 docs on how to handle sessions correctly.
You bootstrap session like this:
use Zend\Session\SessionManager;
use Zend\Session\Container;
class Module
{
public function onBootstrap($event)
{
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$this->bootstrapSession($event);
}
public function bootstrapSession($e)
{
$session = $e->getApplication()
->getServiceManager()
->get('Zend\Session\SessionManager');
$session->start();
$container = new Container('signin');
}
}
If your $member
is a doctrine entity I would also suggest reading the Doctrine 2 documentation on storing entities in the session