Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

User fields

From MoodleDocs
Revision as of 20:35, 14 July 2021 by David Mudrak (talk | contribs) (Text replacement - "<code php>" to "<syntaxhighlight lang="php">")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Moodle 3.11


Code relating to display of user fields is in the class \core_user\fields in file /user/classes/fields.php.

Overview

This class is normally used when displaying lists of users in a table. It has the following main functions.

  1. Decide which extra user fields (e.g. email, username) should be shown in the table, based on the showuseridentity admin setting, the current context, and the permissions of the user.
  2. Provide lists of fields required for showing user picture or full name.
  3. Provide SQL that can be used within a query to get that information for users.

Custom fields

This class supports two kinds of fields: basic user fields (in the user table) and custom profile fields (in the user_info_data table). Because the queries are more complex when getting custom profile fields, there may be some code that doesn't support custom profile fields.

When fields are listed, a standard field in the user table such as email is called email. A custom profile field, such as one with the shortname frog, is prefixed so that it is referred to as profile_field_frog.

Listing fields

The following examples describe how you can get a list of user fields for a certain situation.

List fields required to display a user picture

$fields = \core_user\fields::for_userpic()->get_required_fields();

This will return an array of fields required for displaying userpic (id, picture, firstname, lastname, ...).

These are the fields you need to have in the user object in order to call the $OUTPUT->user_picture($user) function.

List fields required to display a user's full name

$fields = \core_user\fields::for_name()->get_required_fields();

This returns all fields needed to display a name (firstname, lastname, firstnamephonetic, ...).

These are the fields you need to have in the user object in order to call the fullname($user) function.

List fields required to display a user picture and full name

$fields = \core_user\fields::for_name()->with_userpic()->get_required_fields();

If you need both types of fields, you can combine them by creating the object initially with a 'for' method, and then calling the 'with' method to add a different category of fields.

List fields required to display a user's identity

When displaying a table of users, the name is always included (and sometimes a picture), as above. Other 'identity fields' are configurable using the showuseridentity admin setting, and display only to users who have the permission to see them. For example, it could be configured so that email addresses are shown, or user names, or department, or a custom field. These fields usually display in separate table columns.

Because the capability for the current user depends on the location you are looking at, you need to pass a context when getting these fields.

$fields = \core_user\fields::for_identity($context)->get_required_fields();

The list of fields from this function might include custom profile fields e.g. 'profile_field_frog'. In legacy code which only supports fields on the user table, you can pass false to the second 'allow custom fields' parameter of the function:

$fields = \core_user\fields::for_identity($context, false)->get_required_fields();

Now it won't return any custom profile fields (and your code doesn't support them, which is sad).

Add or remove arbitrary extra fields

Sometimes you might want a list of fields to contain extra fields. You could just add them to the array, but that could cause duplicates in some situations which might result in bugs that only appear in certain settings. Instead, there is a convenient way to include them in these lists:

$fields = \core_user\fields::for_identity($context)->including('email')->get_required_fields();

Alternatively you might want to exclude a field - this would usually be because you know you are going to list that field in a database query separately. It is OK to exclude a field whether or not it is actually included; that way the code will continue to work whatever the field list.

$fields = \core_user\fields::for_name()->excluding('firstname')->get_required_fields();

You can use both including and excluding functions if you want.

Getting SQL

In most cases it is not very useful to just get a list of fields. You also need to create the SQL to obtain the values for the fields.

Let's use a simple example - we are writing code that displays a list of all users in the whole system ordered by their last access date, most recent first. For some reason we are also including deleted users (but maybe we're going to display them differently). Here is a basic SQL query that does this:

$result = $DB->get_records_sql("
        SELECT u.id, u.deleted
          FROM {user} u
      ORDER BY u.lastaccess DESC", [], 0, 10);

Suppose that we also want to include the user's name, and any identity fields that are enabled for the current user. We don't want to include the 'id' or 'deleted' field because they're already included in the query.

We can create a user fields object like this:

$context = \context_system::instance();
$userfields = \core_user\fields::for_name()->with_identity($context)->excluding('id', 'deleted');

The user fields object can create SQL snippets for you like this:

$sql = $userfields->get_sql('u');

This returns an object with the fields 'selects', 'joins', 'params', and (not normally needed) 'mappings'. Here is how you use it with the above SQL query:

$result = $DB->get_records_sql("
        SELECT u.id, u.deleted {$sql->selects}
          FROM {user} u
               {$sql->joins}
      ORDER BY u.lastaccess DESC", $sql->params, 0, 10);

There are many options to the get_sql function, as well as the user table alias shown. For example, you can:

  • Use named parameters instead of ? parameters.
  • Add a prefix (e.g.u_) to all field names in the result to ensure they don't clash with other fields in the query.
  • Rename the userid field e.g. to 'userid'.
  • Turn off the leading comma in the selects list.

This last one might need explaining. By default, the 'selects' list starts with a comma, which means you include it in the query as shown above (without a comma before it). By doing this, it will still work correctly if there are no fields to add (then it returns selects as blank, so there is no 'spare' comma).

Selective field lists

When you have created a user fields object that includes a lot of fields for different purposes, like the one in the above example, you might need to get a list of only some of those fields. The most common use case for this is when deciding on columns to display in a table. In the above example, we don't want a column in the table for every fields in the $userfields object - there doesn't need to be a column for the 'firstnamephonetic' field, for instance. But we do need to know the extra identity fields that are being included, because these should each have a column.

An extra parameter on get_required_fields lets you include only one category of fields from the object:

$extracolumns = $userfields->get_required_fields([\core_user\fields::PURPOSE_IDENTITY]);

Field names

To display those columns you will need a header with a field name. You can get a field name as follows:

$header = \core_user\fields::get_display_name($field);

This works for both standard user table fields e.g. email (it will get the appropriate language string), and for custom fields (it will get the name for the custom field).

Older Moodle versions

Prior to Moodle 3.11 the main functions used to carry out the same jobs were called get_extra_user_fields(), get_extra_user_fields_sql(), user_picture::fields(), and get_all_user_name_fields(). These all work, but are deprecated, in Moodle 3.11.