会话容器中的对象变量总是在 bootstrap 中变为空
object variable in session container is always getting null in bootstrap
我在应用程序模块的 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');
}
这里有什么问题?
更新:
我按照 Wilts 在他的回答中的建议进行了修改。它仍然不起作用,但我稍微修改了代码以存储标量值(电子邮件)而不是对象(成员)。现在它正在运行,所以问题是 为什么会话容器不存储对象而只存储标量变量?
在我的登录操作中,我做了这样的更改
$session = new Container('signin');
//$session->member = $member; //removed
$session->email= $member->email; //New
在bootstrap这样
$session = new Container('signin');
if (!isset($session->email)){
$eventManager->attach(MvcEvent::EVENT_ROUTE, array($this,'routeMatched'), -100);
}
正确处理会话涉及的不仅仅是将变量转储到 Container
实例中。会话不能在不序列化对象的情况下存储对象。这意味着您必须在从会话中解析它们时再次反序列化它们。
使用 SessionManager
为了帮助您管理会话存储,ZF2 有一个 SessionManager
class 我建议您创建一个 SessionManager
来控制您的会话变量。您可以在 official ZF2 docs on how to handle sessions correctly 中阅读更多内容。
你 bootstrap 会话是这样的:
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
是学说实体,我还建议您阅读 the Doctrine 2 documentation on storing entities in the session
我在应用程序模块的 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');
}
这里有什么问题?
更新:
我按照 Wilts 在他的回答中的建议进行了修改。它仍然不起作用,但我稍微修改了代码以存储标量值(电子邮件)而不是对象(成员)。现在它正在运行,所以问题是 为什么会话容器不存储对象而只存储标量变量?
在我的登录操作中,我做了这样的更改
$session = new Container('signin');
//$session->member = $member; //removed
$session->email= $member->email; //New
在bootstrap这样
$session = new Container('signin');
if (!isset($session->email)){
$eventManager->attach(MvcEvent::EVENT_ROUTE, array($this,'routeMatched'), -100);
}
正确处理会话涉及的不仅仅是将变量转储到 Container
实例中。会话不能在不序列化对象的情况下存储对象。这意味着您必须在从会话中解析它们时再次反序列化它们。
使用 SessionManager
为了帮助您管理会话存储,ZF2 有一个 SessionManager
class 我建议您创建一个 SessionManager
来控制您的会话变量。您可以在 official ZF2 docs on how to handle sessions correctly 中阅读更多内容。
你 bootstrap 会话是这样的:
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
是学说实体,我还建议您阅读 the Doctrine 2 documentation on storing entities in the session