symfony Doctrine database session storage

Sessions are normally managed by your server and depending upon how involved you get with the PHP setup you need never know how this data is stored. The default setup for PHP is to store session data in temporary files on the server. So why would we want to change how sessions are handled and what advantage can we gain from any changes we make.

Why use database session management?

Sessions allow you maintain persistence within PHP applications. With every HTTP request a PHP application must re-assign every variable and object needed in your application. Sessions allow you to store data that is required to persist past each HTTP request allowing it to be easily retrieved and used.

Sessions are commonly used when  creating a secure application, used to store the state of a user e.g. if they are logged in or credentials to control access to content.

By storing session data in a database table you are able to create an application interface that will show information about the users that are logged in. This for example could show the number of users logged into the application or show administrators who is logged in.

If you  need to scale your application by adding more than one server, saving your session data in temporary files can lead to major problems. By using database storage you can optimise and unify the session storage, ensuring that session data is always available and consistent.

Obviously there are other solutions for scalable session storage such as APC or MemCache but these solutions are for another post.

How to setup Doctrine database session storage

You first need to add a table to you database schema that will be used to store your session data. Although you can create this table manually, adding it to your scheme also created the model classes that you can later use to interact with the table data.

Session:
  columns:
    id: { type: string(32), primary: true, notnull: true }
    data: { type: string(4000), notnull: true }
    time: { type: integer(4), notnull: true }

Once you have added the table to your schema you can build your model and database:

./symfony doctrine:build-all

You then need to configure your symfony application to use this table to store all session data. To do this you need to modify the factories.yml file for your application. Update your file to include the following lines:

all:
  storage:
    class: sfPDOSessionStorage
    param:
      db_table: session # Name of the table storing the sessions
      db_id_col: id # The primary key column
      db_data_col: data # The column where the session data will be stored
      db_time_col: time # The column where the timestamp of the session will be stored
      database: doctrine # Name of the database connection to use

Once you have modifies your factories.yml file you will need to clear the symfony cache. After that your application should run exactly as it did before except that your users session data will be stored in the database table.

The data column stores all the session data in a serialised form this is deserialized each time a user requests the data. There are many uses for this type of session storage and I hope this brief explanation helps you.

Subscribe to my RSS feed or follow me on twitter to find out about setting up symfony to use APC or MemCache session storage.

Related Articles

Tags: , , ,

20 Responses to “symfony Doctrine database session storage”

  1. Nate Michael December 6, 2009 at 10:40 pm #

    It is absolutely imperative if you’re using Doctrine to specify the ID column as well, the schema should look like this:


    Session:
    columns:
    id: { type: string(32), primary: true, notnull: true }
    data: { type: string(4000), notnull: true }
    time: { type: integer(4), notnull: true }

    If you don’t do this your sessions will not work as Doctrine defaults to adding the ID column as an auto incrementing integer, and symfony stores the session id as an md5 hash.

    Also, in the example you gave, your integer(11) specification is incorrect, it should be integer(4) with Doctrine, the 11 doesn’t represent length directly, you would use the “length: 11″ parameter for that.

  2. Alistair Stead December 7, 2009 at 2:13 pm #

    Thanks for you comment Nate! During my testing I did not experience any problems however I will update the post accordingly. Thanks again for taking the time to submit your comments.

  3. Nate Michael December 7, 2009 at 11:41 pm #

    No problem, Alistair!

    What’s odd is Symfony doesn’t complain about the column with the wrong type, but one of two things happen, a row gets added with the auto-incremented id, and no data is stored, causing the session to not be persistent.

    Or, somehow the md5 sum is able to be translated into a crazy integer, and the session will operate correctly.

    I spend quite a few hours trying to figure out what was going on. =P

  4. Christopher Shennan December 8, 2009 at 12:09 pm #

    A very nice, easy to follow tutorial. Now I have my sessions for my latest symfony project nicely stored in the database :)

    Many Thanks.

    Chris.

  5. juanblo January 12, 2010 at 10:45 pm #

    Thanks for the post. The symfony docs aren’t clear about the data type sessions table fields. Thanks again.

  6. Alistair Stead January 12, 2010 at 11:50 pm #

    Your welcome. Most examples provide the SQL to create the table outside of your symfony project. I wanted to show an example using the schema syntax and building the model directly.

  7. Tom January 20, 2010 at 10:50 pm #

    Excellent, thanks for this very straightforward explanation, plus comments from other commenters.

  8. Balazs.2.0 January 26, 2010 at 12:50 am #

    Hello,

    What I’m wondering about (and sorry of this is a newbie question) is that, symfony stores the session data in a serialized form. Can this be changed? More importantly, should this be changed? I usually see session data stored in columns seperately. Does this mean, that each time session data is requested, you have to de-serialize it? Does that effect performance?

    Thanks

  9. Alistair Stead February 13, 2010 at 10:07 am #

    Hi,

    Symfony uses the standard PHP session handler. Due to how a session must be stored and retrieved between each HTTP request the data is stored in a serialized form. Unless you are storing large object structures in session this should not cause you any problems. I’m unsure of your requirements to store data in columns?

    I would suggest that you should possibly look at adding additional protected variables to the myUser class and then create getter and setter methods that will retrieve the data from session. You can then access the data through a common interface.

  10. victor February 17, 2010 at 12:19 pm #

    Hi,

    You said that by storing sessions in a database you are able to retrieve logged in users. Could you please give an example of how to do this?

  11. Alistair Stead February 20, 2010 at 7:00 am #

    Hi,

    You can simple make a select on the session tabe and count the results. If everything is setup correctly the data rows are deleted after a user leaves the site.

  12. victor February 20, 2010 at 10:13 pm #

    Yes, I know that. But I refer to specific users, not at the number of logged in users.

  13. tmv March 23, 2010 at 2:10 pm #

    to define id column can be use param fixed:true then id field will be fixed size char(32) not varchar(32) and performance should be better.

    id: { type: string(32), primary: true, notnull: true, fixed:true }

    Thanks for this great tutorial!

  14. Saad March 30, 2010 at 8:10 pm #

    Hi,
    Great post! I just used it because the prod servers we had to use were load-balanced and we were not able to install memcache.
    The only concern I have: how to clear timed-out sessions? We created a (really simple) symfony task for that, because we weren’t sure if there is some “symfony magic” that automatically clears sessions. I haven’t find any. If you don’t clear expired sessions, I think the DB table will grow infinitely, right?

  15. Alistair Stead April 6, 2010 at 9:21 pm #

    Depending upon you ini config the sessions should be removed automatically.

  16. Jestep September 23, 2010 at 3:28 pm #

    Has anyone implemented session persistence while using a database storage mechanism? I’ve been trying to implement persistent sessions while using a Propel storage for the session data. Doing it without getting overly complicated is becoming more difficult that I originally thought.

  17. Alistair Stead September 24, 2010 at 8:53 am #

    Hi,

    Your sessions stores in the database would still be cleaned by the default php session handler. If you wish to implement persistent sessions you can look at the sfGuard plugin for the remember me keys. This uses a persistent browser cookie that includes a hash to re-authenticate the user when they return to the site.

    A word of warning however persistent sessions compromise security of your application. People can gain access to your application without the need for a password if the cookie exists on a machine. SO don’t use this on public computers.

    -A

  18. Sergey February 18, 2011 at 12:23 pm #

    Hi! Can you help me? I’m need to get some data from user session by another user. Another user is FMS, which know session_id of user and which need to know some information stored in session of this user, how can i get it? session_data is serialized by symfony in database, so i cat get this data by query to db, but simple php function unserialize() doesn’t work…

  19. Rafael June 21, 2011 at 12:47 pm #

    @Sergey

    You have to remove the string “symfony/user/sfUser/configurations|” from the beginning of your session_data.

    Do something like this:

    $session_data = str_replace(“symfony/user/sfUser/configurations|”, “”, $session_data);
    unserialize($session_data);

Trackbacks/Pingbacks

  1. Merci Symfony « Tout sur Rien - April 12, 2010

    [...] Alistair Stead pour son article « symfony Doctrine database session storage« [...]

Leave a Reply