объектная переменная в контейнере сеанса всегда получает значение null в начальной загрузке

Я реализовал логику в начальной загрузке модуля приложения, которая будет перенаправлять пользователей на страницу входа, если они не подписаны. у меня есть

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

person dejjub-AIS    schedule 03.11.2015    source источник
comment
Сеанс запущен в этот момент в вашем приложении?   -  person Magnus Eriksson    schedule 03.11.2015
comment
Я думал, что Zend\Session\Container справится внутри   -  person dejjub-AIS    schedule 03.11.2015


Ответы (1)


Правильная обработка сеансов включает в себя гораздо больше, чем просто сброс ваших переменных в экземпляр Container. Сеанс не может хранить объекты без их сериализации. Это означает, что вам нужно снова десериализовать их при разрешении их из сеанса.

Используйте диспетчер сессий

Чтобы помочь вам управлять хранилищем сеансов, в ZF2 есть класс SessionManager, я предлагаю вам создать класс SessionManager, чтобы получить контроль над переменными сеанса. Подробнее о том, как правильно обрабатывать сеансы.

Вы загружаете сеанс следующим образом:

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 является доктриной, я бы также посоветовал прочитать документацию Doctrine 2 по хранению сущностей в сеансе

person Wilt    schedule 03.11.2015
comment
Можете ли вы написать что-нибудь о решении? Вы предлагаете переместить проверку внутри прослушивателя событий? Почему? - person dejjub-AIS; 03.11.2015
comment
@SolowDeveloper Я добавил больше пояснений к своему ответу - person Wilt; 03.11.2015
comment
не могли бы вы увидеть мой обновленный вопрос? Проблема не в том, что контейнер сеанса не создается в начальной загрузке, а в том, что он имеет дело со скалярными и объектными значениями, которые может хранить контейнер сеанса. - person dejjub-AIS; 06.11.2015
comment
@SolowDeveloper Я обновил свой ответ. Я понял, что ошибка была не в использовании события начальной загрузки. Вы не можете напрямую хранить объекты в контейнере сеанса, как вы это делаете. - person Wilt; 06.11.2015