I am writing an algorithm which will produce some values that I'd like stored in session variables for easy retrival in multiple blocks.

The method I have been using so far is just using $_SESSION['var'] variables.

However, I was looking into variable_set() and variable_get() and I think those kind of do the same thing.

The thing is, the variables I am creating with my algorithm must be unique to each individual end user who visits my site. It seems variable_get() is intended for variables which will apply for ALL users, like form information.

So I am wondering, what is the "Drupal" way of storing session information for individual users? (Or is the $_SESSION variable method the way to go?)

Thanks

Comments

markj’s picture

The way I understand it, $_SESSION values are session-specific since they last only as long as the user's session. variable_set() is used for module and site configuration variables. If the variables you want to use in your blocks are intended to last only for the user's current session, then use $_SESSION['var']. If you want values to persist across sessions, you'll probably need to create a module that uses its own table to store user variables.

esend7881’s picture

Cool thanks, quick follow up question though:

How long are sessions set to last for? Till the user leaves the site or after a set amount of time?

EDIT: To answer my own question, this session period is set in the settings.php file.
ini_set('session.cache_expire', 200000);

markallenneil’s picture

I wrote some code which I've been considering packaging as a module... enclosed herein. This code gives anonymous users the benefit of "remember me" and registered users "remember me, indefinitely, from any computer." You can see it in action at www.authorcollector.com.

- If a user is registered (has a non-zero UID), preferences are stored in a database (in the code below, database 'user_preferences').
- Preferences for unregistered users are stored in a session variable $_SESSION['my_module'].
- Data is serialized into a single value field, so no prior knowledge of field names or structure is required.
- If a value is retrieved which has not been set, you'll get an empty string. I suppose this could be improved to support defaults or changed to return a NULL.
- Note this code makes no attempt to sanity check the input (no check_plain)... this is left up to the client.

Usage:
1) Getting a single session variable...

$prefs = get_user_preferences('customer_name');
// $prefs contains the session value for 'customer_name' (or is an empty string is never set)
// I find the single value syntax useful for forms... i.e. '#default_value' => get_user_preferences('customer_name').

2) Getting multiple session variables...

$prefs = get_user_preferences(array('customer_name', 'customer_address'));
// $prefs['customer_name'] and $prefs['customer_address'] are populated (or empty strings if they'd never been set)

3) Setting one or more session variables...

set_user_preferences(array('customer_name' => 'Mark Allen Neil'));
set_user_preferences(array('customer_name' => 'Mark Allen Neil', 'customer_address' => '123 Main Street'));

Here is the code... I generally package this as 'user.prefs.inc' and then include it in files which manage preferences.

<?php
// $Id: user.prefs.inc $

/**
 * @file
 * Saves and loads user preferences.
 * 
 * Registered users preferences are stored in a database, anonymous user data in session.
 *
 */
 
function get_user_preferences($input) { 
  $prefs = _get_user_preferences(); 
  if (is_array($input)) {    // Input is an array of names
    $output = array();
    foreach ($input as $name) {
      if (isset($prefs[$name])) {    
        $output[$name] = $prefs[$name];
      }
      else {
        $output[$name] = '';
      }
    }
  }
  else {                    // Input is a single name
    if (isset($prefs[$input])) {    
      $output = $prefs[$input];
    }
    else {
      $output = '';
    }
  }
  return $output;
}

function set_user_preferences($in_prefs) {
  $prefs = _get_user_preferences();
  foreach ($in_prefs as $name => $value) {
    $prefs[$name] = $value;
  } 
  _set_user_preferences($prefs);
}

function _get_user_preferences() {
  global $user;
  if ($user->uid) { // Registered user, preferences in database
    $result = db_query("SELECT value FROM {user_preferences} WHERE uid = '%d'", $user->uid);
    if ($result) {
      return unserialize(db_result($result));
    }   
  }
  else {            // Anonymous user, preferences in cookies
    if (isset($_SESSION['my_module'])) {
      return $_SESSION['my_module'];      
    } 
  }
  return array();  
}

function _set_user_preferences($prefs) {
  global $user;
  if ($user->uid) { // Registered user, preferences in database  
    $serialized_prefs = serialize($prefs); 
    db_query("UPDATE {user_preferences} SET value = '%s' WHERE uid = '%d'", $serialized_prefs, $user->uid);
    if (!db_affected_rows()) {
      @db_query("INSERT INTO {user_preferences} (uid, value) VALUES ('%d', '%s')", $user->uid, $serialized_prefs);
    }
  }
  else {            // Anonymous user, preferences in session
    if (!isset($_SESSION['my_module'])) {
      $_SESSION['my_module'] = array();
    }
    foreach ($prefs as $name => $value) {
      $_SESSION['my_module'][$name] = $value;
    }
  }
}

And the following is the code in your module's install file... "my_module.install"...

function my_module_schema() {
  $schema['user_preferences'] = array(
    'fields' => array(   
      'uid' => array('type' => 'int', 'not null' => 'TRUE', 'default' => '0'),
      'value' => array('type' => 'text', 'size' => 'big', 'not null' => TRUE),     
    ),
    'primary key' => array('uid'),
  );   
  return $schema;
}
esend7881’s picture

Wow that looks awesome.

I'd be very interested in seeing that as a module.

Do you have a project page, if I get a chance I could look into it and offer a hand if I can.

markallenneil’s picture

Thanks for the positive feedback... :)

Nope, no projects page. But probably about time for me to take that step... I suspect this would be useful as a module.

Can you wait a day or two? Might take me that long to post something which wouldn't embarrass me.

Mark

PS. I may even have undersold this a bit. The following works... a more complex example of user preferences...

<?php
  include('./sites/all/modules/my_module/user.prefs.inc');
  set_user_preferences(array(
    'Customer' => array(
      'Name' => 'Mark Allen Neil',
      'Phone' => '012-345-6789',
      'Address' => array('Line 1' => '123 Main Street', 'Line 2' => '', 'City' => 'Athens', 'State' => 'Georgia', 'Zip' => '12345')
    )));
  
  $customer = get_user_preferences('Customer');
  print '<pre>Customer: '. print_r($customer, true) .'</pre>';  
  print '<pre>Address only: ' . print_r($customer['Address'], true) .'</pre>';
  print '<pre>Zip only: '. print_r($customer['Address']['Zip'], true) .'</pre>';
?>

Outputs...

Customer: Array
(
    [Name] => Mark Allen Neil
    [Phone] => 012-345-6789
    [Address] => Array
        (
            [Line 1] => 123 Main Street
            [Line 2] => 
            [City] => Athens
            [State] => Georgia
            [Zip] => 12345
        )

)

Address only: Array
(
    [Line 1] => 123 Main Street
    [Line 2] => 
    [City] => Athens
    [State] => Georgia
    [Zip] => 12345
)

Zip only: 12345
mdlamar’s picture

Hey Mark,

I'm curious if you ever packaged your code into a module. It's nice and looks like it could help a lot of people out. Seems like an easy upkeep to for future core releases.

Best,
Milo

bsenftner’s picture

Wow. This is GREAT!

I've been searching for a concise example of using the Drupal DB outside of the context of creating a custom content type, and this has everything I've been looking for...

splash112’s picture

Used you code in my own custom module. Sadly, somehow people seem to get mixed up. I use the "module" to safe user preferences, but somehow these will be mixed sometime between users....

Any idea why?

Mark