Jump to content

Help with SessionHandlerInterface


jebriggsy

Recommended Posts

Hello,

 

I'm writing a quick roll-your-own blog to get back into the swing of webdev, and I've hit a snag.  I'm trying to use session_set_save_handler to use a custom class of functions, implementing SessionHandlerInterface, to save sessions to a PostgreSQL database table via PDO.  I've added die() at every point I think it could be failing but no errors are reported.  I checked nginx, php-fpm, and postmaster logs, nothing.  The thing I'm trying to debug is the fact that no rows are inserted to the database after setting a random test variable in $_SESSION and calling session_write_close().  I know the script is successfully connecting to the database because no exceptions or errors are thrown, so there must be some error that isn't being reported by PDO or the session handler.

 

Basically PDOStatement::rowCount() is returning > 0 for a query inserting a row into the sessions table but upon a SELECT * on said table nothing is there.

 

So I've attached/bpaste'd the relevant files. Here's what's in them:

 

index.php: the script that runs everything

database.php: database functionality

main.php: instantiates database for session & other classes.  also contains the function to test session/database functionality

sessions.php: class implementing SessionHandlerInterface

 

SQL for the sessions table:

CREATE TABLE sessions (
        session_id      bytea           PRIMARY KEY,
        session_expires integer         NOT NULL,
        session_data    text            NOT NULL,
        session_ip      varchar(39)     NOT NULL,
        user_id         integer
);
Any help or insight would be much appreciated.

index.php

database.php

main.php

sessions.php

Link to comment
Share on other sites

A custom session handler is pretty much the worst starting point you can think of, because even experienced developers constantly get this wrong. And indeed this is a typical naïve implementation without any concurrency handling whatsoever. Using Ajax or running a slow script multiple times in quick succession is enough to break the whole thing and end up with strange errors.

 

Proper session handlers are much more complex and require a deep understanding of how to handle concurrency at database level (locks, transactions etc.). For the time being, just stick to classical file-based sessions. Or if you absolutely must store the sessions in the database, use an existing implementation which actually works (there aren't many). For example, the Symfony framework gets it right. They're using advisory locks to make sure that concurrent requests won't overwrite each other.

Link to comment
Share on other sites

A custom session handler is pretty much the worst starting point you can think of, because even experienced developers constantly get this wrong. And indeed this is a typical naïve implementation without any concurrency handling whatsoever. Using Ajax or running a slow script multiple times in quick succession is enough to break the whole thing and end up with strange errors.

I think you may be underestimating my level of competency. I'm doing this project to buff out rust not re-learn basics. I'm not a complete noob, just someone who hasn't done serious coding in a year or three.

 

I intended to implement transactions once I had the basic prototype working. I don't need concurrency when I'm the only one using the software at the moment and nowhere near the point where I'm writing AJAX requests ;) Indeed, eventually I will implement stored procedures, transactions, GPG-based two-factor auth, and maybe a bit of OAuth if I'm feeling adventurous. I'm just stuck on why PDO/PostgreSQL is returning > 0 affected rows on an INSERT that has obviously failed because the table is empty and yet hasn't thrown any exceptions, errors, notices, or warnings.

 

I've always used MySQL and Apache with custom-rolled auth and session systems. I chose a project implementing SessionHandlerInterface using PostgreSQL and Nginx specifically to avoid using old habits that are probably outdated and force me to catch up with modern techniques and design flows. And specifically avoiding frameworks so as to develop a deeper understanding of the concepts.

Edited by jebriggsy
Link to comment
Share on other sites

the error is most likely in your main.php/sesstest() method - 

$count = $this->db->exec('SELECT * FROM sessions');

the pdo ->exec() method does NOT return results for a SELECT query and since a select query does not affect any rows, this usage will always return a zero, which is probably what you are basing the statement that the table is empty on. only insert, delete, update, and replace queries affect rows.

 

you would need to get a row count using a method available for PostgreSQL (which i am not well versed with.) if you cannot get a count in the query statement, doing a pdo fetchall() of the result set and using php count() of the resultant array is the most universal method that would work with all database types.

 

edit: if the PDOStatement::rowCount() method works for PostgreSQL, you would use the pdo query() method to run the query and get a count of the number of rows.

Link to comment
Share on other sites

I think you may be underestimating my level of competency.

 

And I think you're overestimating it.

 

The concept is simply naïve, sorry. You have two options now: You can build some half-assed amateur solution with the help of PHP Freaks. Or you can adopt a professional solution from people who actually know what they're doing (like the Symfony team).

 

Most PHP programmers go with the half-assed solution, which is why they stay amateur programmers for their entire life. But maybe you're one of the few people who takes their job seriously and wants to do it right. Your choice.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.