2

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);            
        }
dejjub-AIS
  • 1,501
  • 2
  • 24
  • 50

1 Answers1

0

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.

Use a SessionManager

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');
    }
}

Storing doctrine entities

If your $member is a doctrine entity I would also suggest reading the Doctrine 2 documentation on storing entities in the session

Wilt
  • 41,477
  • 12
  • 152
  • 203
  • Can you pls write something about the solution? Are you suggesting to move check inside event listener? Why? – dejjub-AIS Nov 03 '15 at 14:51
  • @SolowDeveloper I added more explanation to my answer – Wilt Nov 03 '15 at 14:54
  • can you please see my updated question? The issue doesn't seems like session container ot created in bootstrap but looks like dealing with scalar and object values the session container can store – dejjub-AIS Nov 06 '15 at 08:19
  • @SolowDeveloper I updated my answer. I realized the mistake was not in using bootstrap event. You cannot directly store objects in the session container like you do. – Wilt Nov 06 '15 at 08:37