I have rudimentary knowledge of SQL (when it comes to anything but single tables) and am trying to come up with a query that will give me all the custom fields for my users.
This query will give me all my users sorted by group:
$query = $db->getQuery(true)
->select('name, email, id')
->from($db->quoteName('#__users', u))
->join('LEFT', $db->quoteName('#__user_usergroup_map', map) . ' ON ' . $db->quoteName('map.user_id') . ' = ' . $db->quoteName('u.id'))
->where('map.group_id' . ' = ' . $group)
->order('`name` ASC');
which produces:
SELECT name, email, id
FROM `#__users` AS `u`
LEFT JOIN `#__user_usergroup_map` AS `map` ON `map`.`user_id` = `u`.`id`
WHERE map.group_id = 10
ORDER BY `name` ASC
but I'm puzzled how to add the custom fields that are in the user context (com_users.user) and pertain to each user (based on id). Joins are something I'm just not familiar with in practice. And, Joomla's shorthand for SQL is something else I'm still puzzling through.
While I wouldn't mind just getting the pieces that would make this work, I'm also interested in the how and why - unless that's way too much for a single question.
UPDATE: having tried a few things, I find I can get all the values in the fields, but then I get repeated records - for each user, I get all the user info plus ONE field - repeated for as many fields per user as there are. What I'm wanting is ONE user with all the field data (hopefully with field names) so I can present that on a page. Here's what I tried:
$query = $db->getQuery(true)
->select('u.name, u.email, u.id, fv.value')
->from($db->quoteName('#__users', u))
->join('LEFT', $db->quoteName('#__user_usergroup_map', map) . ' ON ' . $db->quoteName('map.user_id') . ' = ' . $db->quoteName('u.id'))
->join('RIGHT', $db->quoteName('#__fields_values', fv) . ' ON ' . $db->quoteName('fv.item_id') . ' = ' . $db->quoteName('u.id'))
->where('map.group_id' . ' = ' . $group)
->order('`name` ASC');
Update: 1/24 - @mickmackusa - thanks for pushing me on this.
What I did was execute a query on all the fields so I had the names. Then, I executed a query to get all the records (one field per record). Then I combined all the records into one array and passed the fields and records to the tmpl/default.php script.
Here's the queries and joining the records:
// let's try this: get all the field value names per category
$query = $db->getQuery(true);
$query
->select('fields.title')
->from($db->quoteName('#__fields', fields))
;
$db->setQuery($query, 0, 0);
$fv_list = $db->loadObjectList();
//array_unshift($fv_list, "name", "email");
//print_r($fv_list);
// now get all the fields_values
$q1 = $db->getQuery(true);
$q1
->select('u.name, u.email, f.title, fv.value')
->from($db->quoteName('#__users', u))
->join('INNER', $db->quoteName('#__user_usergroup_map', map) . ' ON ' . $db->quoteName('map.user_id') . ' = ' . $db->quoteName('u.id'))
->join('INNER', $db->quoteName('#__fields_values', fv) . ' ON ' . $db->quoteName('fv.item_id' ) . ' = ' . $db->quoteName('u.id'))
->join('INNER', $db->quoteName('#__fields', f) . ' ON ' . $db->quoteName('fv.field_id') . ' = ' . $db->quoteName('f.id'))
// ->where('map.group_id' . ' = ' . $group)
->order('`name` ASC')
;
$db->setQuery($q1, 0, 0);
$fields = $db->loadObjectList();
// echo $q1 .EOL . EOL;
//print_r($fields);
foreach ($fields as $fv)
{
$name = $fv->name;
$list[$name][0] = $name;
$list[$name][1] = $fv->email;
$list[$name][$fv->title] = $fv->value;
}
return (array($fv_list, $list));
This produces an array of two arrays - the first is the list of field names, the second is one record per user with all the fields they've populated as key/value pairs.
In default.php, I output ALL the fields either with data the user populated or "" if the field is empty.
I'm still working on getting the data exported - but the two queries here work on Joomla 4.0.x databases, although I'm not getting group filtering like I want.
#__fields_values
table typically contains multiple rows for a given "id" -- this is deliberate. The table allows you to store multiple pieces of data for a single entity (e.g. a user's hometown, bloodtype, favorite comic book hero, etc). You are likely to need to specify an additional filter to access a particular field value or use aggregate functions. To make your question more clear, please offer a db-fiddle and your desired result.field_id
ANDitem_id
instead of only joining onitem_id
. And aLEFT JOIN
will be appropriate.