3

How can I load multiple nodes in Drupal 6?

It seems that node_load() only returns one record. I need to fetch all the nodes created by a user.

2 Answers 2

4

In Drupal 7, they addressed your use case with node_load_multiple(), and support for Drupal 6 is going to end soon, so if you are planning upgrade, consider postponing your work until then.

In Drupal 6, only way I know of is to use db_query() to join {users} to {node}, or just apply WHERE to {node}, and then loop over it with node_load().

You can pass an "array of conditions to match against in the database query" to node_load(), but it will return one node only anyway, so that's not a solution.

You can also define your own node_load_multiple(), taking the code from the original node_load() and replacing $node = db_fetch_object with the following:

$nodes = array();
while($node = db_fetch_object) {
  // original processing
  $nodes[$node->nid] = $node;
}

Aggregate inside. I'm actually a bit surprised nothing like that is in core, but it's a way too late to propose it now.

1
  • No idea how I was ever able to code on Drupal 6 without node_load_multiple. It seems absolutely crucial now. Commented Nov 11, 2015 at 10:56
1

You could use the following function.

function node_load_by_user_id($uid = NULL) {
  $nodes = array();

  if (is_null($uid)) {
    $uid = $GLOBALS['user']->uid;
  }

  $fields = drupal_schema_fields_sql('node', 'n');
  $fields = array_merge($fields, drupal_schema_fields_sql('node_revisions', 'r'));
  $fields = array_merge($fields, array('u.name', 'u.picture', 'u.data'));
  $fields = array_diff($fields, array('n.vid', 'n.title', 'r.nid'));
  $fields = implode(', ', $fields);
  $fields = str_replace('r.timestamp', 'r.timestamp AS revision_timestamp', $fields);
  $fields = str_replace('r.uid', 'r.uid AS revision_uid', $fields);

  $query = db_query('SELECT ' . $fields . ' FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.vid = n.vid WHERE u.uid = %d', $uid)

  while ($node = db_fetch_object($query)) {
    if ($node->nid) {
      if ($extra = node_invoke($node, 'load')) {
        foreach ($extra as $key => $value) {
          $node->$key = $value;
        }
      }

      if ($extra = node_invoke_nodeapi($node, 'load')) {
        foreach ($extra as $key => $value) {
          $node->$key = $value;
        }
      }

      $nodes[$node->nid] = drupal_clone($node);
    }
  }

  return $nodes;
}

I took the code used by node_load() and adapted it to return an array of nodes created by the same user.

As the function is loading all the nodes created by the user whose ID is passed as argument, this function would probably exhaust all the PHP memory when the user created enough nodes. I would rather use the following function, which loads only a limited number of nodes at time.

function node_load_by_user_id($uid = NULL, $from, $count) {
  $nodes = array();

  if (is_null($uid)) {
    $uid = $GLOBALS['user']->uid;
  }

  $fields = drupal_schema_fields_sql('node', 'n');
  $fields = array_merge($fields, drupal_schema_fields_sql('node_revisions', 'r'));
  $fields = array_merge($fields, array('u.name', 'u.picture', 'u.data'));
  $fields = array_diff($fields, array('n.vid', 'n.title', 'r.nid'));
  $fields = implode(', ', $fields);
  $fields = str_replace('r.timestamp', 'r.timestamp AS revision_timestamp', $fields);
  $fields = str_replace('r.uid', 'r.uid AS revision_uid', $fields);

  $query = db_query_range('SELECT ' . $fields . ' FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.vid = n.vid WHERE u.uid = %d', $uid, $from, $count)

  while ($node = db_fetch_object($query)) {
    if ($node->nid) {
      if ($extra = node_invoke($node, 'load')) {
        foreach ($extra as $key => $value) {
          $node->$key = $value;
        }
      }

      if ($extra = node_invoke_nodeapi($node, 'load')) {
        foreach ($extra as $key => $value) {
          $node->$key = $value;
        }
      }

      $nodes[$node->nid] = drupal_clone($node);
    }
  }

  return $nodes;
}

In this case the function should be called changing the second parameter to get the next nodes.

$from = 0;
$count = 50;
while ($nodes = node_load_by_user_id($uid, $from, $count)) {
  // Use $nodes.
  $from += $count;
}
2
  • where should I put these functions?
    – hd.
    Commented May 24, 2013 at 12:01
  • I take you are asking because you are writing a module; then, you should add one of the two versions of the function in your module. The function should be renamed basing on the name of the module, since every function implemented by a module should have a name prefixed by the module name.
    – apaderno
    Commented May 24, 2013 at 12:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.