Zf2 Db会话插入但不更新数据库中的会话

时间:2014-01-20 08:04:02

标签: php database session zend-framework zend-framework2

我在zf2(骨架)应用程序中配置了数据库会话,以使用文档中所述的典型MySQL数据库。但是,应用程序仅插入会话,它从不更新特定行。因此,每次刷新时都会创建一个新会话,并且无法检索以前存储的信息。

我的配置如下:

global.php
-------------------


        'session_config'    =>  array
                                (
                                    'cache_expire'          =>  2419200,
                                    'cookie_lifetime'       =>  2419200,
                                    'gc_maxlifetime'        =>  2419200,
                                    'cookie_path'           =>  '/',
                                    'cookie_secure'         =>  TRUE,
                                    'remember_me_seconds'   =>  2419200,
                                    'use_cookies'           =>  true,
                                )

我的会话表创建如下(数据库用户有select,insert和amp; update privs):

CREATE TABLE `sessions` 
(
  `id` char(32) NOT NULL DEFAULT '',
  `name` varchar(255) NOT NULL,
  `modified` int(11) DEFAULT NULL,
  `lifetime` int(11) DEFAULT NULL,
  `data` text,
  PRIMARY KEY (`id`)
) 
ENGINE=InnoDB 
DEFAULT CHARSET=utf8

我的数据库会话在Application / Module.php中的工厂闭包中配置:

public function getServiceConfig()
{
    return  array
    (
    'factories' => array
        (
        // Sessions
        'session_manager' => function($serviceManager)
        {
            $sessionOptions = new DbTableGatewayOptions();
            $sessionOptions->setDataColumn('data')
                           ->setIdColumn('id')
                           ->setModifiedColumn('modified')
                           ->setLifetimeColumn('lifetime')                                                                                                 
                           ->setNameColumn('name');                                                                                         
            $dbAdapter              =   $serviceManager->get('utils-db');                                                                                        
            $sessionTableGateway    =   new TableGateway('sessions', $dbAdapter);                                                                                        
            $sessionGateway         =   new DbTableGateway
                                            ($sessionTableGateway, $sessionOptions);                                                                                        
            $config                 =   $serviceManager->get('config');                                                                                        
            $sessionConfig          =   new SessionConfig();                                                                                        
            $sessionConfig->setOptions($config['session_config']);                                                                                        
            $sessionManager         =   new SessionManager($sessionConfig);                                                                                        
            $sessionManager->setSaveHandler($sessionGateway);

            return $sessionManager;
        },
        ...
        ...
        ),
    );
}

会话在onBootstrap方法中启动:

public function onBootstrap(MvcEvent $e)
{
    $eventManager           =   $e->getApplication()->getEventManager();
    $serviceManager         =   $e->getApplication()->getServiceManager();
    $moduleRouteListener    =   new ModuleRouteListener();
    $moduleRouteListener->attach($eventManager);

    $sessionManager         =   $serviceManager->get('session_manager');
    $sessionManager->start();
    Container::setDefaultManager($sessionManager);

    ...

}

我可以从概念上理解zf2可以写入/插入到会话中,但它既不能选择特定行,也不能找到它无法更新的特定行。所以我挖到了Zend \ Session \ SaveHandler并在DbTableGateway类中找到了它:

/**
 * Write session data
 *
 * @param string $id
 * @param string $data
 * @return bool
 */
public function write($id, $data)
{
    $data = array(
        $this->options->getModifiedColumn() => time(),
        $this->options->getDataColumn()     => (string) $data,
    );

    $rows = $this->tableGateway->select(array(
        $this->options->getIdColumn()   => $id,
        $this->options->getNameColumn() => $this->sessionName,
    ));

    if ($row = $rows->current()) {
        return (bool) $this->tableGateway->update($data, array(
            $this->options->getIdColumn()   => $id,
            $this->options->getNameColumn() => $this->sessionName,
        ));
    }
    $data[$this->options->getLifetimeColumn()] = $this->lifetime;
    $data[$this->options->getIdColumn()]       = $id;
    $data[$this->options->getNameColumn()]     = $this->sessionName;

    return (bool) $this->tableGateway->insert($data);
}

显然基于条件,如果为真,它将更新,如果不是,则在下面进行插入:

if ($row = $rows->current()) {
        return (bool) $this->tableGateway->update($data, array(
            $this->options->getIdColumn()   => $id,
            $this->options->getNameColumn() => $this->sessionName,
        ));
    }

对我来说奇怪的是行

if ($row = $rows->current()) {

变量$ row似乎没有在上面设置,但$ rows确实以正确的select语句结束:

SELECT `sessions`.* FROM `sessions` WHERE `id` = :where1 AND `name` = :where2
id is set correctly
name is set correctly

我无法弄清楚为什么我无法更新我的观点。顺便说一句,我可以很好地从应用程序中的会话中读取数据。但是一旦页面刷新,所有数据都消失了。

1 个答案:

答案 0 :(得分:1)

如果您没有通过HTTPS运行应用程序完全,则应将会话配置选项cookie_secure更改为false(或省略它 - 默认为{{1 }})。当false设置为cookie_secure时,Cookie将仅通过HTTPS发送。

在HTTP请求中,这将导致为每个请求创建一个新会话,因为请求中不存在会话cookie。