Zf2 Session

Session in Zend Framework for most people is a bit of mystery. Most people have confusion regarding using of Zend Framework session. So let me try open the puzzling knots for you. Zend Framework Session comes in two sets of classes. One a Session Manager, second a Container. As Zend Framework people trying to teach us that separate each functionality of a system among classes. That is why its been broken into two classes.

Lets first look at Session Manager. Session manager task is to handle task from starting a session to where a session is going to be stored and how its going to be stored. Plus it also assigned task to handle things like session hijacking by injecting session validators classes. As far as session data storage is concerned Zend Framework provides Session Container class.

Session container class stores all your data and it should be used to retrieve and save data in a session. Lets look at how Zend Framework guides us to use session. You can see the example with code here. I will try to explain what happens in that code. The code for global.php or local.php is fairly simple. In the code below we are just telling Zend Framework what we will be using when creating a session.

<?php
return array(
    'session' => array(
        'config' => array(
            'class' => 'Zend\Session\Config\SessionConfig',
            'options' => array(
                'name' => 'myapp',
            ),
        ),
        'storage' => 'Zend\Session\Storage\SessionArrayStorage',
        'validators' => array(
            'Zend\Session\Validator\RemoteAddr',
            'Zend\Session\Validator\HttpUserAgent',
        ),
    ),
);

Now lets look at the code which needs to be placed in the Module.php.

<?php

namespace YourNameSpace;

use Zend\Session\SessionManager;
use Zend\Session\Container;
use Zend\Mvc\ModuleRouteListener;

class Module
{
    public function onBootstrap($e)
    {
        $eventManager        = $e->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);
        $this->bootstrapSession($e);
    }

    public function bootstrapSession($e)
    {
        $serviceManager = $e->getApplication()->getServiceManager();
        $session = $serviceManager->get('Zend\Session\SessionManager');
        $session->start();

        //Changed the code a bit. Because its not good to use new Container();
        $container = $serviceManager->get('MySessionService');

        if (!isset($container->init)) {
            
            $request        = $serviceManager->get('Request');

            $session->regenerateId(true);
            $container->init          = 1;
            $container->remoteAddr    = $request->getServer()->get('REMOTE_ADDR');
            $container->httpUserAgent = $request->getServer()->get('HTTP_USER_AGENT');

            $config = $serviceManager->get('Config');
            if (!isset($config['session'])) {
                return;
            }

            $sessionConfig = $config['session'];
            if (isset($sessionConfig['validators'])) {
                $chain   = $session->getValidatorChain();

                foreach ($sessionConfig['validators'] as $validator) {
                    switch ($validator) {
                        case 'Zend\Session\Validator\HttpUserAgent':
                            $validator = new $validator($container->httpUserAgent);
                            break;
                        case 'Zend\Session\Validator\RemoteAddr':
                            $validator  = new $validator($container->remoteAddr);
                            break;
                        default:
                            $validator = new $validator();
                    }

                    $chain->attach('session.validate', array($validator, 'isValid'));
                }
            }
        }
    }

    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'Zend\Session\SessionManager' => function ($sm) {
                    $config = $sm->get('config');
                    if (isset($config['session'])) {
                        $session = $config['session'];

                        $sessionConfig = null;
                        if (isset($session['config'])) {
                            $class = isset($session['config']['class'])  ? $session['config']['class'] : 'Zend\Session\Config\SessionConfig';
                            $options = isset($session['config']['options']) ? $session['config']['options'] : array();
                            $sessionConfig = new $class();
                            $sessionConfig->setOptions($options);
                        }

                        $sessionStorage = null;
                        if (isset($session['storage'])) {
                            $class = $session['storage'];
                            $sessionStorage = new $class();
                        }
                        // Save handler is responsibe to store information in database or file or memcache
                        $sessionSaveHandler = null;
                        if (isset($session['save_handler'])) {
                            // class should be fetched from service manager since it will require constructor arguments
                            $sessionSaveHandler = $sm->get($session['save_handler']);
                        }

                        $sessionManager = new SessionManager($sessionConfig, $sessionStorage, $sessionSaveHandler);
                    } else {
                        $sessionManager = new SessionManager();
                    }
                    Container::setDefaultManager($sessionManager);
                    return $sessionManager;
                },
            ),
            'invokables' => array(
                'mySessionService' => 'Zend\Session\Container',
            ),
        );
    }

    public function getViewHelperConfig()
    {
        return array(
            'factories' => array(
                'mySessionService' => function ($sm) {
                    $locator = $sm->getServiceLocator();
                    $viewHelper = new View\Helper\Session;
                    $viewHelper->setSession($locator->get('mySessionService'));
                    return $viewHelper;
                },
            )
        );
    }
}

Now you can use your session in controllers via the below code.

<?php

namespace YourNameSpace\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class IndexController extends AbstractActionController{
     public function indexAction(){
         $sessionContainer = $this->getServiceLocator()->get('mySessionService');
         var_dump($sessionContainer->offsetGet('init'));
     }
}

To use it in any layout or *.phtml file you've to create a view helper. Create a class in YouNameSpace\View\Helper\Session.php


<?php

namespace YourNameSpace\View\Helper;

use Zend\View\Helper\AbstractHelper;

class Session  extends AbstractHelper{
    
    protected $container = null; 
    
    public function __invoke(){
        return $this;
    }
    
    public function setSession(\Zend\Session\AbstractContainer $container){
        $this->container = $container;
        return $this;
    }
    
    public function getSession() {
        return $this->container;
    }
}

That would be all. I hope you guys have understood how to use Sessions in Zend Framework. Next I will be discussing ZfcUser. Enjoy and please if it helps you in any way please do comment.