I stumbled on this without fully understanding the implications.

In user.module user_load() function, right after it queries the {users} database, all the bio data come out as well.

function user_load($array = array()) {
  $result = db_query('SELECT * FROM {users} u WHERE '. implode(' AND ', $query), $params);

  if (db_num_rows($result)) {
    $user = db_fetch_object($result);
    $user = drupal_unpack($user);

The db_fetch_object() returns the $user with bio data. It turned out that those additional bio data were serialized by drupal in db when the user was first created. I don't know if this can be potentially a problem? I don't know if the un-serialized data match the actual bio data from the content_type_bio table. If an application uses this un-serialized data, can it cause problem?

I may play more with it and report back my finding.

#3 biofieldcleanup.patch582 bytessethcohn
Members fund testing for the Drupal project. Drupal Association Learn more


marcvangend’s picture

Interesting to read this, I didn't know about this drupal_unpack function and what it does within user_load.

This behavior turned out to be a problem for me today. I was creating a block with some author information, fetched the user object of the node's author, printed it to the screen and thought "Cool! The bio fields are already in the user object!". However, when I made changes to the bio node, they were not reflected in the user object. I did notice the serialized ['data'] value, but the concept that it contains the initial values rather than the current values did not cross my mind.

So what should we do? I don't know. It confused me, it might confuse others, and that's a pity. On the other hand, nothing is really broken.

sethcohn’s picture

Category: support » bug

After discovering that a 'private' field (using private number cck) was also being saved into the user node, as serialized (non-privatized) data, I realized that Bio isn't doing the right thing here:

From http://api.drupal.org/api/function/hook_user/5 :

"insert": The user account is being added. The module should save its custom additions to the user object into the database and set the saved fields to NULL in $edit.


function bio_user($op, &$edit, &$account, $category = NULL) {
  switch ($op) {

    case 'insert':
      return bio_user_register_submit($edit);

function bio_user_register_submit($form_values) {
  // Create bio node for this user.
  $node = new StdClass;
  $node->type = bio_get_type();
  $node->uid = db_result(db_query("SELECT uid FROM {users} WHERE name = '%s'", $form_values['name']));
  $node->title = $form_values['name'];
  $node->name = $form_values['name'];

  $node_options = variable_get('node_options_'. $node->type, array('status', 'promote'));
  foreach (array('status', 'promote', 'sticky') as $key) {
    $node->$key = in_array($key, $node_options);
  // Always use the default revision setting.
  $node->revision = in_array('revision', $node_options);
  foreach ($form_values as $field_name => $value) {
    if (preg_match('/^field_/', $field_name)) {
      $node->$field_name = $form_values[$field_name];

  // Create the node.
  $node = node_submit($node);

  // Give us a nice log message.
  if ($node->nid) {
    watchdog('content', t('Bio: added %user bio upon registration.', array('%user' => $node->name)), WATCHDOG_NOTICE, l(t('view'), "node/$node->nid"));

No place in the above are the saved fields nulled out, so they go on to be saved in $data in the user object. A simple additional nulling of the original form_values once those fields are IDed via the preg_match should fix this.

sethcohn’s picture

Version: 5.x-1.2 » 5.x-1.x-dev
Status: Active » Needs review
582 bytes

patch enclosed, please test but it works for me.