Attached is a patch (against HEAD, includes tests) which allows users to
extend any session handler in an object oriented fashion.
By extending the new internal class SessionHandler, users can wrap or
override methods of whatever session handler is in use, or implement a
complete custom handler.
Usage notes:
- Calling session_set_save_handler(class) after session_set_save_handler(a,
b, c, d, e, f) wouldn't transparently extend the first call since they share
the same storage. However this can be achieved by calling the former
functions manually from the class. - Likewise multiple session_set_save_handler(class) calls simply replace
each other; just extend the new class from the old one instead of
SessionHandler to chain them.
Implementation notes:
- mod_user.c was faking PS(mod_data) so it would get called at the right
times. Now that we need to preserve the data for whatever handler we're
wrapping, session.c checks the new global PS(mod_active) instead. No more
tests are failing but I think it's possible this could break existing user
session modules so please look at this carefully. We could just do
PS(mod_data) || PS(var_controlled_by_mod_user) to be on the safe side, at
the expense of a very slight overhead for other session modules.
I've experimented with a few different ways of approaching this already.
Although I like this one (reusing the mod_user callbacks) because the change
is pretty minimal, it might be better to just store a pointer to the class
entry or the function entries. Or something entirely different..
I'd be grateful for any comments.
Arpad
Attached is a patch (against HEAD, includes tests) which allows users to extend any session handler in an object oriented fashion.
By extending the new internal class SessionHandler, users can wrap or override methods of whatever session handler is in use, or implement a complete custom handler.
Usage notes:
- Calling session_set_save_handler(class) after session_set_save_handler(a, b, c, d, e, f) wouldn't transparently extend the first
sounds useful. i assume with this i could extend for example the session handler that comes with the Memcached extension? could you provide a code example of how that would look like?
regards,
Lukas Kahwe Smith
mls@pooteeweet.org
On Fri, Nov 27, 2009 at 11:57 AM, Lukas Kahwe Smith mls@pooteeweet.orgwrote:
sounds useful. i assume with this i could extend for example the session
handler that comes with the Memcached extension? could you provide a code
example of how that would look like?
Right, the SessionHandler class represents the current save handler,
whichever it is. Here's a minimal example:
<?php
class MySession extends SessionHandler {
public static function read($id) {
echo "hi!";
return parent::read($id);
}
}
session_set_save_handler('MySession');
session_start()
;
?>
There's a few more examples in the phpt in the patch.
Regards,
Arpad
Hi!
By extending the new internal class SessionHandler, users can wrap or
override methods of whatever session handler is in use, or implement a
complete custom handler.
Couple of notes:
- I'd call mod_active something more clean - like session_active?
- What happens if session module is set to "user" in configuration -
what old_mod will be then and how this patch will work? - old_mod is also not a clear name - maybe default_mod?
- I think it also makes sense to allow passing object instead of class.
- In fact, thinking about it - maybe it should be an interface and not
a class?
--
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Hi!
By extending the new internal class SessionHandler, users can wrap or
override methods of whatever session handler is in use, or implement a
complete custom handler.
Hi,
Thanks very much for your feedback, I've made some changes in the attached
patch.
Couple of notes:
- I'd call mod_active something more clean - like session_active?
This flag indicates whether the mod should be called from the usual session
events. There might be a better name for it but there's already a
session_active with a different meaning.
- What happens if session module is set to "user" in configuration - what
old_mod will be then and how this patch will work?
It now raises an error rather than segfaulting if the user module is
selected but no handler has been registered. This should really halt
execution which it doesn't at the moment but I'll raise that separately.
old_mod is only set in the first call to session_set_save_handler()
, so
subsequent calls just replace each other. Inheritance can be achieved by
extending the previous class or calling the previous functions from the new
class.
- old_mod is also not a clear name - maybe default_mod?
Ok, changed.
- I think it also makes sense to allow passing object instead of class.
I've allowed objects to be passed now but I think this should probably be
discouraged since it's going to be called in a static context anyway.
- In fact, thinking about it - maybe it should be an interface and not a
class?
I made it a class rather than an interface to allow easy inheritance of the
default handler. This way it's always parent::foo() whether extending
directly from SessionHandler or a child class. It also means users only need
to implement the methods they actually use.
Regards,
Arpad
Hi!
2. What happens if session module is set to "user" in configuration - what old_mod will be then and how this patch will work?
It now raises an error rather than segfaulting if the user module is
selected but no handler has been registered. This should really halt
execution which it doesn't at the moment but I'll raise that separately.
I'd say if it's "user" then it should return an error from the
set_handler function.
4. I think it also makes sense to allow passing object instead of class.
I've allowed objects to be passed now but I think this should probably
be discouraged since it's going to be called in a static context anyway.
I don't see anything inherently wrong with having session object.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Hi,
It now raises an error rather than segfaulting if the user module is
selected but no handler has been registered. This should really halt
execution which it doesn't at the moment but I'll raise that separately.I'd say if it's "user" then it should return an error from the set_handler
function.
Do you mean when session_set_save_handler()
is called more than once? That's
quite harmless and I think it would be useful to wrap frameworks' session
handlers.
The error I'm talking about is when the ini setting session.save_handler is
set to user - we get this during module start-up when the ini settings are
registered.
This is an erroneous configuration since we have no way of registering the
user handlers at that time.
4. I think it also makes sense to allow passing object instead of
class.
I've allowed objects to be passed now but I think this should probably
be discouraged since it's going to be called in a static context anyway.I don't see anything inherently wrong with having session object.
I don't think that there's anything inherently wrong with it, just that it's
slightly inefficient and offers no benefits since $this isn't available.
Regards,
Arpad