Search Drupal User Profiles
It is difficult to search for users (in code) based on profile information in Drupal 6 due to the flexible nature in which the profiles module stores information.
Basically profiles are stored in 2 tables.
mysql> select * from profile_fields; +-----+------------+-------------------+-------------+---------------------+------+-----------+--------+----------+----------+------------+--------------+---------+ | fid | title | name | explanation | category | page | type | weight | required | register | visibility | autocomplete | options | +-----+------------+-------------------+-------------+---------------------+------+-----------+--------+----------+----------+------------+--------------+---------+ | 1 | First Name | profile_firstname | | General Information | | textfield | 0 | 0 | 1 | 1 | 0 | | | 2 | Last Name | profile_lastname | | General Information | | textfield | 0 | 0 | 1 | 1 | 0 | | +-----+------------+-------------------+-------------+---------------------+------+-----------+--------+----------+----------+------------+--------------+---------+ 2 rows in set (0.00 sec)
select * from profile_values limit 4; +-----+-----+---------+ | fid | uid | value | +-----+-----+---------+ | 1 | 1 | John | | 2 | 1 | Doe | | 1 | 115 | John | | 2 | 115 | Smith | +-----+-----+---------+ 4 rows in set (0.00 sec)With only one value per row it is difficult to create a generic function to search for multiple values at once. We could examine both tables and hard code a mysql function using multiple joins for each fid but that isn'r very reusable. Thankfully the mysql GROUP_CONCAT function comes to the rescue. Combined with a simple function to get profile field definitions it is possible to search for users based on profile information. Here are two simple functions I came up with that make it easy to search for users based on profile information in drupal
/** * dgs_get_profile_fields * @return array(name => fid) */ function dgs_get_profile_fields($category = null){ if(isset($profile_fields)){ return $profile_fields; } static $profile_fields = array(); $sql = "SELECT * FROM {profile_fields}"; $args = array(); if(!empty($category)){ $sql .= " WHERE category='%s'"; $args= array($category); } $result = db_query($sql,$args); while($row = db_fetch_object($result)){ $profile_fields[$row->name] = $row->fid; } return $profile_fields; } /** * dgs_search_profiles * @param(array(fieldname => fieldvalue)); * @return an array of user uids */ function dgs_search_profiles($params = array()){ //Example SQL //SELECT GROUP_CONCAT(fid,'=',value) as profile from profile_values GROUP BY(uid) HAVING profile like "%1=Gary%" AND profile like "%2=Varnell%"; $profile_fields = dgs_get_profile_fields(); $having = array(); $args = array(); foreach($params as $fieldname => $fieldvalue){ $having[] = "profile LIKE '%s'"; $args[] = "%" . $profile_fields[$fieldname] . "=$fieldvalue%"; } $having = join('AND ',array_values($having)); $result = db_query("SELECT uid,GROUP_CONCAT(fid,'=',value) as profile from profile_values GROUP BY(uid) HAVING $having",$args); $users = array(); while($row = db_fetch_object($result)){ $users[$row->uid] = user_load($row->uid); } return $users; }And here is a usage example
$users = dgs_search_profiles(array('profile_firstname' => 'John','profile_lastname' => 'Doe')); print_r($users);Which returns
Array ( [xxx] => stdClass Object ( [uid] => xxx [name] => jdoe [pass] => xxxxxxxx [mail] => jdoe@somewhere.com [mode] => 0 [sort] => 0 [threshold] => 0 [theme] => [signature] => [signature_format] => 0 [created] => 1264712914 [access] => 1318017735 [login] => 1317926353 [status] => 1 [timezone] => -21600 [language] => [picture] => [init] => xxxxx [data] => a:1:{s:13:"form_build_id";s:37:"form-xxxxxxxxxxxxxxxxxxxxx";} [form_build_id] => form-xxxxxxxxxxxxxxxxx [roles] => Array ( [2] => authenticated user [3] => xxxxxxx [5] => xxxxxxx ) [profile_firstname] => John [profile_lastname] => Doe )If you have a better solution please let me know, and as always feel free to comment.