4

Is it safe to overwrite the super-global $_SESSION with a specialised session object?

class SessionObject implements ArrayAccess { ... }

...

// Session data has just been deserialised from store.
$_SESSION = new SessionObject( $session_data );

...

// Using session object...
$_SESSION['key'] = 27;
$x = $_SESSION->get_data('key2', 'default-value');
hakre
  • 193,403
  • 52
  • 435
  • 836
Lea Hayes
  • 62,536
  • 16
  • 62
  • 111
  • i think it will get destroyed later better use $_SESSION['obj'] and handle proper serialization – venimus Jun 13 '11 at 17:03
  • Do you handle the session storage yourself or do you want to rely on phps default $_SESSION behaviour? – mario Jun 13 '11 at 17:04
  • @venimus It doesn't appear to, so far as I can tell... – lonesomeday Jun 13 '11 at 17:05
  • 1
    @venimus I have written custom session persistence logic. For technical reasons I am not using `session_start`, but instead a custom `Session::start` function. Don't know if this has any baring on your thought. – Lea Hayes Jun 13 '11 at 17:08
  • well if you don't use session_start then $_SESSION is simply a variable and should be safe to use – venimus Jun 13 '11 at 17:09

3 Answers3

6

While this may work, I don't think it's sensible behaviour. The principle of least surprise applies, in my opinion, to programming as much as to user interface design. If you overwrite the default behaviour of $_SESSION in your script, that's going to confuse the hell out of some future programmer who has to deal with your code.

I think it's a hack -- and an unpleasant one -- to abuse the super-global nature of $_SESSION in this way.

Better, in my opinion, would be to write a class with static methods to get and set your data:

class Session {
    public function get($key, $defaultValue = null) {
        // do some code to get the value for $key, and return $defaultValue if there is none
    }

    public function set($key, $value) {
        // do some code to set $key
    }
}

You could then access this with Session::get('someKey') or Session::get('someKey', 'default') and Session::set('someKey', 'someValue').

Since classes are inherently global, you could access this from anywhere in your code. It is less surprising, and will result in less confusion down the line.

If you did want to use object methods for some design reason, it might be best to implement the Singleton pattern.

lonesomeday
  • 233,373
  • 50
  • 316
  • 318
  • that's pretty much what I have at the moment, but it doesn't make it very easy to interact with arrays: `$_SESSION['something']['in']['array'] = 27` and using `$a = Session::get('something'); $a['in']['array'] = 26; Session::set('something', $a);` incurs lots of array copies – Lea Hayes Jun 13 '11 at 17:15
  • 3
    Then implement the [Singleton](http://php.net/manual/en/language.oop5.patterns.php#language.oop5.patterns.singleton) pattern, which would result in code like `$session = Session::getInstance(); $session['something']['in']['array'] = 27;` – lonesomeday Jun 13 '11 at 17:16
1

Seems a little risky to me. Have you checked out the session_set_save_handler method? It lets you designate your own handler to use, instead of trying to overwrite $_SESSION.

Steven Mercatante
  • 24,757
  • 9
  • 65
  • 109
  • I am not using native PHP sessions at all, I am using a custom implementation. – Lea Hayes Jun 13 '11 at 17:09
  • 1
    @Lea: using the set_save_handler stuff, you can impose your own session semantics on PHP's default session handler. You get the benefits of the _SESSION superglobal, but provide all the logic to populate/save the session. PHP will call your provided handlers at the appropriate times when you use the normal session_*() functions. – Marc B Jun 13 '11 at 17:44
1

If you deal with session handling and storage yourself, then you can do whatever you please. The $_SESSION superglobal can be used like any other variable in that regard.

It's only PHPs default session handler which treats it specially. It expects a normal array there (and must not be numerically indexed as well). If you wanted to use that again, you would require to undo the fancy ArrayObject wrapping with a shutdown call:

register_shutdown_function(function(){
    $_SESSION = (array)$_SESSION;
});
mario
  • 144,265
  • 20
  • 237
  • 291