> Symfony中文手册 > 如何使用MongoDbSessionHandler存储session到MongoDB数据库

如何使用MongoDbSessionHandler存储session到MongoDB数据库

默认的Symfony session存储,是把session信息写入到文件中(译注:Symfony默认基于PHP原生session handler)。某些中大型网站使用一个Nosql数据库叫做Mongodb来存储session值而是不使用文件,这是因为在“服务器集群”环境下数据库更容易使用和升级。

对于NoSQL数据库的session存储,Symfony有一个内置的解决方案叫做 MongoDBSessionHandler。MongoDB是一个开源的Document数据库,提供了高性能、高可用性和自动升级等特性。本文假定你已经安装和配置一个MongoDB服务器完毕。为了使用它,你只需在主配置文件中改变/添加一些参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# app/config/config.yml
framework:
    session:
        # ...
        handler_id:  session.handler.mongo
        cookie_lifetime: 2592000 # optional, it is set to 30 days here
        gc_maxlifetime: 2592000 # optional, it is set to 30 days here

services:
    # ...
    mongo_client:
        class: MongoClient
        # if using a username and password
        arguments: ['mongodb://%mongodb_username%:%mongodb_password%@%mongodb_host%:27017']
        # if not using a username and password
        arguments: ['mongodb://%mongodb_host%:27017']
    session.handler.mongo:
        class: Symfony\Component\Httpfoundation\Session\Storage\Handler\MongoDbSessionHandler
        arguments: ['@mongo_client', '%mongo.session.options%']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance"
    xmlns:framework="http://symfony.com/schema/dic/symfony"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        http://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/symfony
        http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
 
    <framework:config>
        <!-- ... -->
 
        <!-- cookie-lifetime and gc-maxlifetime are optional and set to
             30 days in this example -->
        <framework:session handler-id="session.handler.mongo"
            cookie-lifetime="2592000"
            gc-maxlifetime="2592000"
        />
    </framework:config>
 
    <services>
        <service id="mongo_client" class="MongoClient">
            <!-- if using a username and password -->
            <argument>mongodb://%mongodb_username%:%mongodb_password%@%mongodb_host%:27017</argument>
 
            <!-- if not using a username and password -->
            <argument>mongodb://%mongodb_host%:27017</argument>
        </service>
 
        <service id="session.handler.mongo" class="Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler">
            <argument type="service">mongo_client</argument>
            <argument>%mongo.session.options%</argument>
        </service>
</container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Definition;
 
$container->loadFromExtension('framework', array(
    'session' => array(
        // ...
        'handler_id'      => 'session.handler.mongo',
        'cookie_lifetime' => 2592000, // optional, it is set to 30 days here
        'gc_maxlifetime'  => 2592000, // optional, it is set to 30 days here
    ),
));
 
$container->setDefinition('mongo_client', new Definition('MongoClient', array(
    // if using a username and password
    array('mongodb://%mongodb_username%:%mongodb_password%@%mongodb_host%:27017'),
    // if not using a username and password
    array('mongodb://%mongodb_host%:27017'),
)));
 
$container->setDefinition('session.handler.mongo', new Definition(
    'Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler',
    array(new Reference('mongo_client'), '%mongo.session.options%')
));

上面用到的参数应该被定义在程序中的某处,一般位于你的主参数配置文件中:

1
2
3
4
5
6
7
8
9
# app/config/parameters.yml
parameters:
    # ...
    mongo.session.options:
        database: session_db # your MongoDB database name
        collection: session  # your MongoDB collection name
    mongodb_host: 1.2.3.4 # your MongoDB server's IP
    mongodb_username: my_username
    mongodb_password: my_password
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance"
    xmlns:framework="http://symfony.com/schema/dic/symfony"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        http://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/symfony
        http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
 
    <parameters>
        <parameter key="mongo.session.options" type="collection">
            <!-- your MongoDB database name -->
            <parameter key="database">session_db</parameter>
            <!-- your MongoDB collection name -->
            <parameter key="collection">session</parameter>
        </parameter>
        <!-- your MongoDB server's IP -->
        <parameter key="mongodb_host">1.2.3.4</parameter>
        <parameter key="mongodb_username">my_username</parameter>
        <parameter key="mongodb_password">my_password</parameter>
    </parameters>
</container>
1
2
3
4
5
6
7
8
9
10
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Definition;
 
$container->setParameter('mongo.session.options', array(
    'database'   => 'session_db', // your MongoDB database name
    'collection' => 'session',  // your MongoDB collection name
));
$container->setParameter('mongodb_host', '1.2.3.4'); // your MongoDB server's IP
$container->setParameter('mongodb_username', 'my_username');
$container->setParameter('mongodb_password', 'my_password');

设置MongoDB Collection ¶

因为MongoDB使用了dynamic collection schhemas,你不需要做任何事来初始化你的session collection。然而,你也许希望添加一个索引来改进garbage collection的性能。从MongoDB shell中可以发现:

1
2
use session_db
db.session.ensureIndex( { "expires_at": 1 }, { expireAfterSeconds: 0 } )