会话容器中的对象变量在引导程序中总是为null


object variable in session container is always getting null in bootstrap

我在应用程序模块的引导程序中实现了一个逻辑,如果用户没有签名,该逻辑将重定向到登录页面。我有

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

正如您在下面看到的,onBootstrap内部的代码将检查会话容器是否没有设置member变量,如果没有设置,则会附加EVENT_ROUTE,它在内部处理要做的事情,具体取决于当前路由是否为白名单。

        $session = new Container('signin');
        if (!isset($session->member)) ...

这里的问题是$session->member总是得到null。我在我的控制器内的登录操作中分配这个变量,就像这个

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

这里有什么问题?

更新:

我按照威尔茨在答复中的建议做了修改。它仍然不起作用,但我稍微修改了代码,以存储标量值(电子邮件)而不是对象(成员)。现在它正在工作,所以问题是为什么会话容器不存储对象,而只存储标量变量

在我的签名操作中,我做了类似的更改

                $session = new Container('signin');
                //$session->member = $member; //removed
                $session->email= $member->email; //New

在像这样的引导程序中

        $session = new Container('signin');
        if (!isset($session->email)){
           $eventManager->attach(MvcEvent::EVENT_ROUTE, array($this,'routeMatched'), -100);            
        }

正确处理会话比简单地将变量转储到Container实例要多得多。会话无法在不序列化对象的情况下存储对象。这意味着您必须在从会话中解析它们时再次反序列化它们。

使用会话管理器

为了帮助您管理会话存储ZF2有一个SessionManager类,我建议您创建一个SessionManager来控制会话变量。您可以在ZF2官方文档中阅读更多关于如何正确处理会话的内容。

你的引导会话是这样的:

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

存储条令实体

如果您的$member是条令实体,我还建议阅读条令2关于在会话中存储实体的文档