4

複数のアプリケーション間ですばやくインストールできるように、DB セッション モジュールを作成するのに忙しいのです。モジュールは、開始する最初のモジュールとしてオートローダーからロードされます。私が達成しようとしているのは、デフォルトのセッションコンテナ/セッションハンドラーをすべてのモジュールのデフォルトのセッションハンドラーに変更することであり、データベースがホストするセッションでもある必要があります。私はかなり長い間zf2セッションハンドラーに苦労してきましたが、ログのエラーは意味がありません。だからここに私がこれまで持っているものがあります。Module.php を含む基本モジュール...

名前空間 DBSession;

use Zend\Mvc\ModuleRouteListener;

class Module {

    public function onBootstrap($e) {
        $e->getApplication()->getServiceManager()->get('translator');
        $eventManager = $e->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);
        $config = $e->getApplication()->getServiceManager()->get('Config');
        $controller = $e->getTarget();
        $controller->config = $config;
        new \DBSession\Storage\DBStorage();
    }

    public function getConfig() {
        return include __DIR__ . '/config/module.config.php';
    }

    public function getAutoloaderConfig() {
        return array(
            'Zend\Loader\ClassMapAutoloader' => array(
                __DIR__ . '/autoload_classmap.php',
            ),
            'Zend\Loader\StandardAutoloader' => array(
                'namespaces' => array(
                    __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                ),
            ),
        );
    }
}

そして、DB セッション ハンドラーを開始する実際のクラス。

namespace DBSession\Storage;

use Zend\Session\SaveHandler\DbTableGateway;
use Zend\Session\SaveHandler\DbTableGatewayOptions;
use Zend\Db\Adapter\Adapter;
use Zend\Session\SessionManager;
use Zend\Session\Container;

class DBStorage {

    public function __construct() {
        $dbAdapter = new Adapter(array(
                    'driver' => 'Mysqli',
                    'host' => 'localhost',
                    'dbname' => 'zf2_session',
                    'username' => 'zf2',
                    'password' => 'testme',
                    'options' => array(
                        'buffer_results' => true,
                    ),
                ));

        $tableGateway = new \Zend\Db\TableGateway\TableGateway('session', $dbAdapter);


        $gwOpts = new DbTableGatewayOptions();
        $gwOpts->setDataColumn('data');
        $gwOpts->setIdColumn('id');
        $gwOpts->setLifetimeColumn('lifetime');
        $gwOpts->setModifiedColumn('modified');
        $gwOpts->setNameColumn('name');


        $saveHandler = new DbTableGateway($tableGateway, $gwOpts);
        $sessionManager = new SessionManager();
        $sessionManager->setSaveHandler($saveHandler);
        return Container::setDefaultManager($sessionManager);
    }

}

セッションを作成しようとすると、ログに次のように表示されますが、修正方法の手がかりがありません。魔法が嫌いになってきました…

[29-Nov-2012 20:47:28 UTC] PHP Fatal error:  Uncaught exception 'Zend\Db\Sql\Exception\InvalidArgumentException' with message 'Not a valid magic property for this object' in /document_root/vendor/zendframework/zendframework/library/Zend/Db/Sql/Select.php:764
Stack trace:
#0 /document_root/vendor/zendframework/zendframework/library/Zend/Db/Sql/Select.php(163): Zend\Db\Sql\Select->__get('tableReadOnly')
#1 /document_root/vendor/zendframework/zendframework/library/Zend/Db/Sql/Select.php(146): Zend\Db\Sql\Select->from('session')
#2 /document_root/vendor/zendframework/zendframework/library/Zend/Db/Sql/Sql.php(65): Zend\Db\Sql\Select->__construct('session')
#3 /document_root/vendor/zendframework/zendframework/library/Zend/Db/TableGateway/AbstractTableGateway.php(191): Zend\Db\Sql\Sql->select()
#4 /document_root/vendor/zendframework/zendframework/library/Zend/Session/SaveHandler/DbTableGateway.php(134): Zend\Db\TableGateway\AbstractTableGateway->select(Array)
#5 [internal function]: Zend\Session\SaveHandler\DbTableGateway->write(' in /document_root/vendor/zendframework/zendframework/library/Zend/Db/Sql/Select.php on line 764
4

3 に答える 3

5

アップデート :

zend フレームワーク >= 2.2、この問題はもうありません。

古い答え:

セッションをデータベースに保存する際に同じ問題に直面しました。基本モジュール クラス内に initDbSession 関数を記述しました。\module\Application\Module.php

class Module
{
    public function onBootstrap(MvcEvent $e)
    {
        $e->getApplication()->getServiceManager()->get('translator');
        $eventManager        = $e->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);

        // session start from here
        $this->initDbSession( $e );

    }


    /** 
     * Store session into database
     * 
     * @param type $e
     */
    private function initDbSession( MvcEvent $e )
    {
        // grab the config array
        $serviceManager     = $e->getApplication()->getServiceManager();
        $config             = $serviceManager->get('config');

        $dbAdapter          = $serviceManager->get('Zend\Db\Adapter\Adapter');

        /* some how this not works for me 
        $sessionOptions = new \Zend\Session\SaveHandler\DbTableGatewayOptions( null );

        $sessionTableGateway = new \Zend\Db\TableGateway\TableGateway('session', $dbAdapter);
        $saveHandler = new \Zend\Session\SaveHandler\DbTableGateway($sessionTableGateway, $sessionOptions);

        */

        /* I written my own save handler , I am using mysql as database */
        $saveHandler   = new \My\Session\SaveHandler\Mysql( $config['db'] );

        $sessionConfig = new \Zend\Session\Config\SessionConfig();
        $sessionConfig->setOptions($config['session']);

        // pass the saveHandler to the sessionManager and start the session
        $sessionManager = new \Zend\Session\SessionManager( $sessionConfig , NULL, $saveHandler );
        $sessionManager->start();

        \Zend\Session\Container::setDefaultManager($sessionManager);

    }    

    // other function goes here ...

ここに私の設定ファイルがあります\config\autoload\global.php

return array(        
        'db' => array(
            'driver'         => 'Pdo',
            'dsn'            => 'mysql:dbname=zf2;host=localhost',
            'driver_options' => array(
                PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'',
                'buffer_results' => true
            ),
            'username'       => 'root',
            'password'       => '',
            'host'           => 'localhost',
            'dbname'         => 'zf2',
        ),         
        'session' => array(
              'remember_me_seconds' => 2419200,
              'use_cookies'       => true,
              'cookie_httponly'   => true,
              'cookie_lifetime'   => 2419200,
              'gc_maxlifetime'    => 2419200,

        ),
        'service_manager' => array(
            'factories' => array(                
                'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory'
            )
        )
);

Mysqlテーブル構造は

CREATE TABLE `session` (
`id` CHAR(32) NOT NULL DEFAULT '',
`name` VARCHAR(255) NOT NULL,
`modified` INT(11) NULL DEFAULT NULL,
`lifetime` INT(11) NULL DEFAULT NULL,
`data` TEXT NULL,
PRIMARY KEY (`id`)
)COLLATE='utf8_general_ci' ENGINE=InnoDB;

カスタム Mysql 保存ハンドラ クラスを以下に示します。Zend\Session\SaveHandler\DbTableGateway newがサーバー上で機能しないため、このクラスを作成しました。私のカスタムMysqlセッション保存ハンドラクラスは上に書かれています\library\My\Session\SaveHandler\Mysql.php

<?php

namespace My\Session\SaveHandler;

use Zend\Session\SaveHandler\SaveHandlerInterface;

/**
 * Description of Mysql
 *
 * @author rab
 */
class Mysql  implements SaveHandlerInterface 
{

    /**
     * Session Save Path
     *
     * @var string
     */
    protected $sessionSavePath;

    /**
     * Session Name
     *
     * @var string
     */
    protected $sessionName;

    /**
     * Lifetime
     * @var int
     */
    protected $lifetime;

    /**
     * Constructor
     *
     */
    public function __construct( $dbConfig )
    {

        $this->dbconn  = mysql_connect(
            $dbConfig['host'],
            $dbConfig['username'], 
            $dbConfig['password']
        );

        if ( $this->dbconn ) {
            return mysql_select_db($dbConfig['dbname'], $this->dbconn);
        }
    }


    /**
     * Open the session
     * 
     * @return bool
     */
    public function open( $savePath, $name )
    {
        $this->sessionSavePath = $savePath;
        $this->sessionName     = $name;
        $this->lifetime        = ini_get('session.gc_maxlifetime');

        return true;

    }


    /**
     * Close the session
     * 
     * @return bool
     */
    public function close() 
    {

        return mysql_close($this->dbconn);
    }


    /**
     * Read the session
     * 
     * @param int session id
     * @return string string of the sessoin
     */
    public function read($id) 
    {

            $id     = mysql_real_escape_string($id);

            $sql    = "SELECT `data` FROM `session` " .
                      "WHERE id = '$id'";

            if ( $result = mysql_query($sql, $this->dbconn)) {
                if ( mysql_num_rows($result) ) {
                    $record = mysql_fetch_assoc($result);
                    return $record['data'];
                }
            }

            return '';
    }


    /**
     * Write the session
     * 
     * @param int session id
     * @param string data of the session
     */
    public function write($id, $data ) 
    {

            $data   = (string) $data ;

            $dbdata = array(
                'modified' => time(),
                'data'     => mysql_real_escape_string( $data  ) ,
            );

            $selectSql = "SELECT * FROM session 
                          WHERE id = '$id' AND name = '{$this->sessionName}' ";

            $rs          = mysql_query( $selectSql, $this->dbconn );

            if ( $rs = mysql_query( $selectSql , $this->dbconn)) {
                if ( mysql_num_rows($rs) ) {

                    $updateSql = "UPDATE `session` SET 
                           `modified`= '".$dbdata['modified'] . "' ,
                           `data`= '".$dbdata['data']. "' 
                            WHERE id= '$id' AND name = '{$this->sessionName}' ";


                    mysql_query( $updateSql ,  $this->dbconn );
                    return true;

                }
            }


            $dbdata['lifetime']  = $this->lifetime;
            $dbdata['id']        = $id;
            $dbdata['name']      = $this->sessionName;

            $insertSql =  "INSERT INTO session (". implode(',' , array_keys($dbdata)) .")"
                           ."VALUES ('" . implode("','" , array_values( $dbdata )). "')";

            return mysql_query( $insertSql, $this->dbconn);

    }


    /**
     * Destoroy the session
     * 
     * @param int session id
     * @return bool
     */
    public function destroy($id) 
    {

            $sql = sprintf("DELETE FROM `session` WHERE `id` = '%s'", $id);
            return mysql_query($sql, $this->dbconn);
    }


    /**
     * Garbage Collector
     * 
     * @param int life time (sec.)
     * @return bool
     */
    public function gc( $maxlifetime ) 
    {

            $sql = sprintf("DELETE FROM `session` WHERE `modified` < '%s'",
                    mysql_real_escape_string(time() - $maxlifetime)
            );

            return mysql_query($sql, $this->dbconn);
    }

}

セッション値を db table に保存します。詳細については、http://php.net/manual/en/function.session-set-save-handler.phpを確認してください。

于 2012-11-30T09:59:43.653 に答える
4

最近 ZF2 に適用されたすべての修正の後、元のソリューションは変更なしで機能するようになりましたが、それを使用したい人のために新しいコンポーザー モジュールを追加しました。これにより、すべて手動で行う必要性が減ります。

インストールの詳細は、https ://github.com/Nitecon/DBSessionStorage の readme ファイルにあります。

楽しんで、問題があればお知らせください。

于 2013-03-29T17:48:01.803 に答える
0

別の同様の解決策があります: Zend Framework 2 で Cookie を使用するには?

この行を必ず変更してください。

Session::setDefaultManager($sessionManager);

これで:

Container::setDefaultManager($sessionManager);

使用:

use Zend\Session\Container;
于 2013-03-12T19:38:18.770 に答える