Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/248.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何使用Zend';s会话管理器?_Php_Session_Zend Framework_Doctrine - Fatal编程技术网

Php 如何使用Zend';s会话管理器?

Php 如何使用Zend';s会话管理器?,php,session,zend-framework,doctrine,Php,Session,Zend Framework,Doctrine,当启动会话时,它会生成会话密钥并将大量数据发布到会话中。但是我已经用我自己的会话密钥和一组不同的会话数据设置了一个会话系统。如何将Zend配置更改为使用我的配置 以下是Zend会话供参考: array (size=2) '__ZF' => array (size=2) '_REQUEST_ACCESS_TIME' => float 1468447555.1396 '_VALID' => array (size=3)

当启动会话时,它会生成会话密钥并将大量数据发布到会话中。但是我已经用我自己的会话密钥和一组不同的会话数据设置了一个会话系统。如何将Zend配置更改为使用我的配置

以下是Zend会话供参考:

array (size=2)
  '__ZF' => 
    array (size=2)
      '_REQUEST_ACCESS_TIME' => float 1468447555.1396
      '_VALID' => 
        array (size=3)
          'Zend\Session\Validator\Id' => string 'xxxxxxxxxxxxxxxxxxxxxxxxxx' (length=26)
          'Zend\Session\Validator\RemoteAddr' => string '--ip addr--' (length=13)
          'Zend\Session\Validator\HttpUserAgent' => string '--user agent info--' (length=114)
  'initialized' => 
    object(Zend\Stdlib\ArrayObject)[371]
      protected 'storage' => 
        array (size=3)
          'init' => int 1
          'remoteAddr' => string '--ip addr--' (length=13)
          'httpUserAgent' => string '--user agent info--' (length=114)
      protected 'flag' => int 2
      protected 'iteratorClass' => string 'ArrayIterator' (length=13)
      protected 'protectedProperties' => 
        array (size=4)
          0 => string 'storage' (length=7)
          1 => string 'flag' (length=4)
          2 => string 'iteratorClass' (length=13)
          3 => string 'protectedProperties' (length=19)
下面是我当前存储的会话信息的样子(它在数据库中,所以我现在用一个条令实体引用它):

我为会话管理器编写的代码来自,因此我提供了一个链接,而不是重新绘制它并把这个问题弄得一团糟


我之所以想使用Zend会话管理器而不是简单地引用我存储的会话信息,是因为我在我的程序和存储的会话信息之间有一个层,这样我就可以在不必更改整个程序的情况下更改访问会话信息的方式。

我最终解决了这个问题通过扩展SessionManager、SessionStorage和SessionSaveHandler类并重写一些功能,我自己也可以做到这一点。我还更改了Module.php和Module.config.php文件。这就是变化的样子:

module.config.php

<?php

/* ...required use statements... */

return array(
    'session' => array(
        'config' => array(
            'class' => 'Zend\Session\Config\SessionConfig',
            'options' => array(
                'name' => [my session name],
            ),
        ),
        'storage' => 'MySession\Model\MySessionStorage',
        'save_handler' => 'MySession\Model\MySessionSaveHandler'
    ),
    'service_manager' => array(
        'factories' => array(
            'session_service' => function($serviceManager) {
                $entityManager = $serviceManager->get('Doctrine\ORM\EntityManager');

                return new SessionService($entityManager, 'MySession');
            },
            'MySession\Model\MySessionSaveHandler' => function($serviceManager) {
                $sess = $serviceManager->get('onmysession_service');
                /* @var $adapter \Zend\Db\Adapter\Adapter */
                $adapter = $sm->get('Zend\Db\Adapter\Adapter');
                $tableGateway = new TableGateway('mytablename', $adapter);
                return new MySessionSaveHandler($tableGateway, new DbTableGatewayOptions(), $sess);
            },
            'MySessionManager' => 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();
                    }

                    $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 MySessionManager($sessionConfig, $sessionStorage, $sessionSaveHandler);
                } else {
                    $sessionManager = new MySessionManager();
                }
                MySession::setDefaultManager($sessionManager);
                return $sessionManager;
            },
        ),
    ),
    'db' => array(
        [db info here]
    ),
    /***************************************************************************************************************
     * Below is the doctrine configuration which holds information about the entities in this module and some
     * other doctrine stuff like orm drivers etc.
     ***************************************************************************************************************/
    'doctrine' => array(
        'driver' => array(
            'session_entities' => array(
                'class' =>'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
                'cache' => 'array',
                'paths' => array(__DIR__ . '/../src/MySession/Entity')
            ),
            'orm_default' => array(
                'drivers' => array(
                    'MySession\Entity' => 'session_entities'
                ),
            ),
        ),
    ),
);
<?php

namespace MySession;

/* ...required use statements... */

/***************************************************************************************************
 * This class holds a few utility functions related to loading the module and accessing config
 * files for the module etc. These functions are primarily used by Zend under the hood.
 ***************************************************************************************************/
class Module implements AutoloaderProviderInterface, ConfigProviderInterface
{
    public function onBootstrap(MvcEvent $e) {
        $eventManager        = $e->getApplication()->getEventManager();

        // create the session manager
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);
        $sessionManager = $e->getApplication()
                            ->getServiceManager()
                            ->get('MySessionManager');
        $sessionManager     ->start();

        // attach dispatch listener to validate user session
        $eventManager->attach(MvcEvent::EVENT_DISPATCH, array($sessionManager, 'handleSessionValidation')); // TODO: we already handleSessionValidation on bootstrap, find out if it's necessary to do it on dispatch as well
    }

    /***************************************************************************************************
     * Returns the location of the module.config.php file. This function is used by the Zend Framework
     * underneath the hood.
     ***************************************************************************************************/
    public function getConfig()
    {
        return include __DIR__ . '/config/module.config.php';
    }

    /***************************************************************************************************
     * Returns the Zend StandardAutoLoader which contains the directory structure of the module source
     * folder.
     ***************************************************************************************************/
    public function getAutoloaderConfig()
    {
        return array(
            'Zend\Loader\StandardAutoloader' => array(
                'namespaces' => array(
                    __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                ),
            ),
        );
    }
}

我通过扩展SessionManager、SessionStorage和SessionSaveHandler类并重写一些功能,最终自己解决了这个问题。我还更改了Module.php和Module.config.php文件。这就是变化的样子:

module.config.php

<?php

/* ...required use statements... */

return array(
    'session' => array(
        'config' => array(
            'class' => 'Zend\Session\Config\SessionConfig',
            'options' => array(
                'name' => [my session name],
            ),
        ),
        'storage' => 'MySession\Model\MySessionStorage',
        'save_handler' => 'MySession\Model\MySessionSaveHandler'
    ),
    'service_manager' => array(
        'factories' => array(
            'session_service' => function($serviceManager) {
                $entityManager = $serviceManager->get('Doctrine\ORM\EntityManager');

                return new SessionService($entityManager, 'MySession');
            },
            'MySession\Model\MySessionSaveHandler' => function($serviceManager) {
                $sess = $serviceManager->get('onmysession_service');
                /* @var $adapter \Zend\Db\Adapter\Adapter */
                $adapter = $sm->get('Zend\Db\Adapter\Adapter');
                $tableGateway = new TableGateway('mytablename', $adapter);
                return new MySessionSaveHandler($tableGateway, new DbTableGatewayOptions(), $sess);
            },
            'MySessionManager' => 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();
                    }

                    $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 MySessionManager($sessionConfig, $sessionStorage, $sessionSaveHandler);
                } else {
                    $sessionManager = new MySessionManager();
                }
                MySession::setDefaultManager($sessionManager);
                return $sessionManager;
            },
        ),
    ),
    'db' => array(
        [db info here]
    ),
    /***************************************************************************************************************
     * Below is the doctrine configuration which holds information about the entities in this module and some
     * other doctrine stuff like orm drivers etc.
     ***************************************************************************************************************/
    'doctrine' => array(
        'driver' => array(
            'session_entities' => array(
                'class' =>'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
                'cache' => 'array',
                'paths' => array(__DIR__ . '/../src/MySession/Entity')
            ),
            'orm_default' => array(
                'drivers' => array(
                    'MySession\Entity' => 'session_entities'
                ),
            ),
        ),
    ),
);
<?php

namespace MySession;

/* ...required use statements... */

/***************************************************************************************************
 * This class holds a few utility functions related to loading the module and accessing config
 * files for the module etc. These functions are primarily used by Zend under the hood.
 ***************************************************************************************************/
class Module implements AutoloaderProviderInterface, ConfigProviderInterface
{
    public function onBootstrap(MvcEvent $e) {
        $eventManager        = $e->getApplication()->getEventManager();

        // create the session manager
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);
        $sessionManager = $e->getApplication()
                            ->getServiceManager()
                            ->get('MySessionManager');
        $sessionManager     ->start();

        // attach dispatch listener to validate user session
        $eventManager->attach(MvcEvent::EVENT_DISPATCH, array($sessionManager, 'handleSessionValidation')); // TODO: we already handleSessionValidation on bootstrap, find out if it's necessary to do it on dispatch as well
    }

    /***************************************************************************************************
     * Returns the location of the module.config.php file. This function is used by the Zend Framework
     * underneath the hood.
     ***************************************************************************************************/
    public function getConfig()
    {
        return include __DIR__ . '/config/module.config.php';
    }

    /***************************************************************************************************
     * Returns the Zend StandardAutoLoader which contains the directory structure of the module source
     * folder.
     ***************************************************************************************************/
    public function getAutoloaderConfig()
    {
        return array(
            'Zend\Loader\StandardAutoloader' => array(
                'namespaces' => array(
                    __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                ),
            ),
        );
    }
}

<?php

namespace MySession\Model;

/* ...required use statements... */

class MySessionStorage extends SessionArrayStorage
{
    /**
     * Set storage metadata
     *
     * Metadata is used to store information about the data being stored in the
     * object. Some example use cases include:
     * - Setting expiry data
     * - Maintaining access counts
     * - localizing session storage
     * - etc.
     *
     * @param  string                     $key
     * @param  mixed                      $value
     * @param  bool                       $overwriteArray Whether to overwrite or merge array values; by default, merges
     * @return ArrayStorage
     * @throws Exception\RuntimeException
     */
    public function setMetadata($key, $value, $overwriteArray = false)
    {
        if ($this->isImmutable()) {
            throw new Exception\RuntimeException(
                sprintf('Cannot set key "%s" as storage is marked isImmutable', $key)
            );
        }

        // set the value
        $sessVar = $_SESSION['_metadata'];
        if (isset($sessVar[$key]) && is_array($value)) {
            // data is array, check if we're replacing the whole array or modify/add to it
            if ($overwriteArray) {
                $sessVar[$key] = $value;
            } else {
                $sessVar[$key] = array_replace_recursive($sessVar[$key], $value);
            }
        } else {
            // data is not an array, set or remove it in the session
            if ((null === $value) && isset($sessVar[$key])) {
                // remove data
                $array = $sessVar;
                unset($array[$key]);
                $_SESSION[SessionVariableNames::$SESSION_METADATA] = $array; // we can't use $sessVar here because it's only a copy of $_SESSION
                unset($array);
            } elseif (null !== $value) {
                // add data
                $sessVar[$key] = $value;
            }
        }

        return $this;
    }

    /**
     * Retrieve metadata for the storage object or a specific metadata key 
     * 
     * Looks at session db for the metadata
     *
     * Returns false if no metadata stored, or no metadata exists for the given
     * key.
     *
     * @param  null|int|string $key
     * @return mixed
     */
    public function getMetadata($key = null)
    {
        if (!isset($_SESSION)) {
            return false;
        }

        if (null === $key) {
            return $_SESSION;
        }

        if (!array_key_exists($key, $_SESSION)) {
            return false;
        }

        return $_SESSION[$key];
    }

    /**
     * Set the request access time
     *
     * @param  float        $time
     * @return ArrayStorage
     */
    protected function setRequestAccessTime($time)
    {
        // make a metadata write call, since that sets a timestamp
        $this->setMetadata('datatime', new DateTime("now"));

        return $this;
    }
}
<?php

namespace MySession\Model;

/* ...required use statements... */

/**
 * This class is the back end of the $_SESSION variable, when used together with a SessionStorage and SessionManager in a ZF module
 */
class MySessionSaveHandler implements SaveHandlerInterface
{
    protected $sessionService;
    private $tableGateway;
    private $options;
    private $sessionName;
    private $sessionSavePath;
    private $lifetime;

    public function __construct(
        TableGateway $tableGateway,
        DbTableGatewayOptions $options,
        ISessionService $sessionService)
    {
        $this->tableGateway = $tableGateway;
        $this->options      = $options;
        $this->sessionService = $sessionService;
    }

    protected function getSessionService()
    {
        return $this->sessionService;
    }

    /**
     * Read session data
     *
     * @param string $id
     * @return string
     */
    public function read($id)
    {
        // Get data from database
        $metadata = $this->readMetadata($id);

        // Put data in PHP-session-serialized form
        $data = "_metadata|".serialize($metadata);
        return $data;
    }

    /**
     * Read session metadata
     *
     * @param string $id
     * @return mixed
     */
    public function readMetadata($id = null)
    {
        if (is_null($id))
        {
            if (!array_key_exists('sessionid', $_COOKIE))
            {
                // can't get id from cookie
                return null;
            }
            $id = $_COOKIE['sessionid'];
        }
        if ($data = $this->getSessionService()->findById($id))
        {
            return $data->getArrayCopy();
        }
        return null;
    }

    /** deprecated, use writeMetadata instead
     * Write session data
     *
     * @param string $id
     * @param string $data
     * @return bool
     * Note sessions use an alternative serialization method.
     */
    public function write($id, $data)
    {
        // don't use this because $data is serialized strangely and can't be automatically inserted into my table
    }

    /**
     * Write session metadata
     *
     * @param string $id
     * @param array $data an associative array matching a row in the table
     * @return mixed
     */
    public function writeMetadata($id = null, $data = null)
    {
        if (is_null($id))
        {
            if (!array_key_exists('sessionid', $_COOKIE))
            {
                // can't get id from cookie
                return null;
            }
            $id = $_COOKIE['sessionid'];
        }

        // get the session info from the database so we can modify it
        $sessionService = $this->getSessionService();
        $session = $sessionService->findByID($id);
        if (is_null($session)) {
            $session = new \MyModule\Entity\MySession();
        }
        if (!is_null($data))
        {
            // overwrite the stored data
            $session->setDataFromArray($data);
        }
        return $sessionService->save($session);
    }

    /**
     * Destroy session - deletes data from session table
     *
     * @param  string $id The session ID being destroyed.
     * @return bool
     * The return value (usually TRUE on success, FALSE on failure).
     * Note this value is returned internally to PHP for processing.
     */
    public function destroy($id)
    {
        $this->getSessionService()->delete($id);

        return true;
    }

    /**
     * Garbage Collection - cleanup old sessions
     *
     * @param int $maxlifetime
     * Sessions that have not updated for
     * the last maxlifetime seconds will be removed.
     * @return bool
     * The return value (usually TRUE on success, FALSE on failure).
     * Note this value is returned internally to PHP for processing.
     */
    public function gc($maxlifetime)
    {
        $metadata = $this->readMetadata(); // gets session id from cookie, then gets session from that
        if (!is_null($metadata))
        {
            $datatime = $metadata['datatime'];
            $previousTime = (new DateTime($datatime))->getTimestamp();

            // if (current time - datatime) > maxlifetime, destroy the session
            $val = time() - $previousTime;
            if ($val > $maxlifetime) {
                $this->destroy($metadata['sessionid']);
            }
        }
    }
}