Extending Drupal Search on other User fields

The default Drupal “search by user” is performed by the hook search_execute implemented by the user module (here is the full code), which searches on the “name” field (if you can administer users it searches also on the email).
But what about searching on other fields?

As a user is an entity on Drupal 7, it can be extended with other fields, such as the first name, the last name, a biography, a city, and so on.
Let’s say we have defined these fields:

  • field_first_name
  • field_last_name
  • field_biography

and we want that searches can be performed also on these fields.
To do so, when using the standard Drupal search and therefore without creating indexes with the Search APIs or with Apache Solr, we can implement two hooks in our module:

/**
 * Implements hook_search_info().
 *
 * @see hook_search_info()
 */
function YOUR_MODULE_search_info() {
  return array(
    'title' => 'People',
  );
}
/**
 * Implements hook_search_execute().
 *
 * @see hook_search_execute()
 */
function YOUR_MODULE_search_execute($keys = NULL, $conditions = NULL) {

   $find = array();
  // Replace wildcards with MySQL/PostgreSQL wildcards.
  $keys = preg_replace('!\*+!', '%', $keys);
  $query = db_select('users', 'u')->extend('PagerDefault');
  $query->distinct();
  $query->fields('u', array('uid'));

  // Additional tables
  $query->join('field_data_field_first_name', 'fn', 'fn.entity_id = u.uid');
  $query->join('field_data_field_last_name', 'ln', 'ln.entity_id = u.uid');
  $query->join('field_data_field_biography', 'sb', 'sb.entity_id = u.uid');

  $query->fields('u', array('mail'));
  $query->condition(
    db_or()
      ->condition('u.name', '%' . db_like($keys) . '%', 'LIKE')
      ->condition('u.mail', '%' . db_like($keys) . '%', 'LIKE')

      // Additional fields
      ->condition('field_first_name_value', '%' . db_like($keys) . '%', 'LIKE')
      ->condition('field_last_name_value', '%' . db_like($keys) . '%', 'LIKE')
      ->condition('field_biography_value', '%' . db_like($keys) . '%', 'LIKE')
  );

  $uids = $query->limit(15)->execute()->fetchCol();
  $accounts = user_load_multiple($uids);

  $results = array();
  foreach ($accounts as $account) {
    $result = array(
      'title' => format_username($account),
      'link' => url('user/' . $account->uid, array('absolute' => TRUE)),
    );
    if (user_access('administer users')) {
      $result['title'] .= ' (' . $account->mail . ')';
    }
    $results[] = $result;
  }

  return $results;
}

The first hook adds an additional ‘People’ (or name it as you like) tab to the Drupal search page which can be enabled in admin/config/search/settings under “Active search modules” (you should uncheck the default “User” tab).
The second hook joins the field’s tables in the query and the value of these fields in the conditions of the query.

In this way a searched key can be found also inside the additional fields of the user.

In order to use Disqus to comment out you have to accept the use of third-party cookies.