derby has asked for the wisdom of the Perl Monks concerning the following question:

Yes I know the title is kinda convoluted but so is my question/request for comment.

I have a fairly straightforward session class that does the normal web session stuff ala CGI::Session and a database backend. Within the session blob, I store normal stuff like access privs, name, salutation, etc and then store the session id in a cookie.

The problem I have is shimming this into legacy code. Given a cgi process (or mod_perl request), I can set the session cookie appropriately and follow on processes/requests work fine; however, some legacy code needs that initial session information further down the request (same process). Unfortunately, the code is so OO (or that should be overOO'ed) that I would need to modify half a dozen classes to pass the session along.

What I'm thinking of doing is making the session class a singleton so that the new method will return the just created session. So instead of doing something like this:

my $session = My::Session->new(); my $foo = Foo->new( session => $session ); # and foo creates Bar passing session, which creates # Baz passing session
I would just do something like this:
my $session = My::Session->new(); my $foo = Foo->new(); ... package Baz; sub new { ... $self->{session} = My::Session->new(); }

Ideally, I'd like to redo the whole app so this isn't a problem, but that's not really feasible. So my question is does this sound feasible? The session class needs to be mod_perl aware but for that, I would just place the singleton reference into pnotes.

-derby

Replies are listed 'Best First'.
Re: RFC Singleton Sessions
by perrin (Chancellor) on Dec 08, 2006 at 01:50 UTC
    I usually just create a session wrapper, so you can call something like MySession->get_sesssion() and it gives you back the session for the current user, dealing with cookies and caching the result as necessary.

      [id://perrin], that makes sense for a normal request when the cookie is sent along with the request (or the session id is embedded in the url). What's probably missing from my OP is that initial request when the cookie is set -- in that case, what is MySession->get_session() doing to retrieve the just created session? You can't get the session id from the cookie (since you've just set it) and I really don't want to pass the session through several methods. In my mind, a singleton (per request) is what's needed but I'm not 100% certain since this is the first time I've had to deal with this particular situation (if I were doing the app from scratch, I'd code it in such a way as not to be in this situation!)

      -derby

        A singleton is basically the same thing as a global variable. In Perl, that's typically how they are implemented -- you put your session object into some package variable in the MySession namespace, or in mod_perl you might put in $r->pnotes.

        What this means for you is that any time you create a session object, either from a cookie or by generating a totally new one and adding a cookie, you keep the session object around in this global for anyone else who needs it during the request. At the end of the request, if you put it in a package variable and not pnotes, you have to make sure to clear it and save the session. Is this making more sense to you now?

Re: RFC Singleton Sessions
by skx (Parson) on Dec 08, 2006 at 12:35 UTC

    Yes that makes a lot of sense. I have a simple Singleton::Session module which I use on one of my projects.

    It uses the MySQL driver, but that is irrelevant here.

    In the code I just use:

    my $session = Singleton::Session->instance(); $session->param( "bob" );
    Steve
    --