Users in WordPress

Basic information you need to know about WordPress users.

Table wp_users

ID(number)
User ID. Specified only if you need to update data for an existing user. All required parameters become optional.
user_login(string) (required)
Login of the new user. To perform additional validation of the login before creation/update, you can use the filter: pre_user_login.
user_pass(string) (required)
Password for the created user. Hashed.
user_nicename(string)
User's name. If not specified, it will be the same as the login. Contains a sanitized login for use in the URL - sanitized through sanitize_title(). For example, if the email [email protected] is provided in the login field during registration, it will result in userexample-com. Used in the link to the author's archive page, so the field value must be unique for each user.
user_email(string)
Email. Checked for existence in the database.
user_url(string)
Website. Filter: pre_user_url.
user_registered(DATETIME)
Registration date. Format: Y-m-d H:i:s. If not specified when creating a user, the current date within the GMT range is taken.
user_activation_key
Hash key for password recovery, created when requested. See get_password_reset_key().
user_status(not used)

This field is no longer used by the WordPress core, which was previously used in Multisite when moving a user to spam (this functionality has been removed). See more in the function: update_user_status().

You can use the column for your own purposes, but it's better to leave it alone.

display_name(string)
Display name. If empty, it will be the same as the login.

Table wp_usermeta

Important meta-data (meta-fields)

wp_capabilities(array)

User role and capabilities: a:1:{s:13:"administrator";b:1;}.

IMPORTANT! The prefix of this option wp_ must match the prefix of the database tables $wpdb->prefix or $wpdb->get_blog_prefix() for multisite.

For example, if the table prefix is changed on the live site in wp-config.php, then the prefix in this option also needs to be manually changed, otherwise all users will lose their rights because after changing the prefix, for example, to wk_, WordPress will look for rights in the meta-field wk_capabilities.

session_tokens
Active sessions. Created when logging into the account.

Other data stored in the metadata table

nickname(string)
Nickname. If empty, it will be the same as the login.
first_name(string)
First name.
last_name(string)
Last name.
description(string)
A little about yourself.
rich_editing(string/bool)
Enable (true) or disable (false) the visual editor. See user_can_richedit().
Default - 'true'
syntax_highlighting(string/bool)
Whether to enable syntax highlighting for the visual editor.
comment_shortcuts(string/bool)
Whether to enable comment moderation shortcuts for the user. Whether to enqueue the script enqueue_comment_hotkeys_js. See enqueue_comment_hotkeys_js().
Default - 'false'
use_ssl(string/bool)
Whether the user should always log in via https.
Default - 'false'
show_admin_bar_front(string)
Whether to show the admin bar on the site or not.
Default - 'true'
role(string)
User role.
Default is taken from the settings: get_option('default_role')
locale(string)
User's language (locale). For example: ru_RU. Since WP 4.7.
Default - ''
default_password_nag(true/false)
true - means that the default password is set.

Also, the metadata contains Admin Panel Options — these are settings for admin pages and more. For example: saved choices of metaboxes on different pages.

meta_key meta_value
admin_color midnight
closedpostboxes_dashboard a:0:{}
metaboxhidden_dashboard a:4:{i:0;s:17:"dashboard_primary";i:1;s:24:"tinypng_dashboard_widget";i:2;s:18:"dashboard_activity";i:3;s:21:"dashboard_quick_press";}
closedpostboxes_{POST_TYPE} a:1:{i:0;s:11:"commentsdiv";}
metaboxhidden_{POST_TYPE} a:3:{i:0;s:7:"slugdiv";i:1;s:13:"trackbacksdiv";i:2;s:11:"commentsdiv";}
meta-box-order_dashboard
meta-box-order_{POST_TYPE}
meta-box-order
wp_media_library_mode Can be: list or grid. See upload.php
show_welcome_panel 0
show_admin_bar_front true
wp_user-settings
deprecated: wp_usersettings
editor=tinymce&editor_expand=off&libraryContent=browse&dtmenuRight=1&mfold=o&posts_list_mode=list
wp_user-settings-time
deprecated: wp_usersettingstime
1604820217
dismissed_wp_pointers Various notes that need to be shown to the user in the admin panel. Can store the following keys: theme_editor_notice,wp330_toolbar,wp330_media_uploader,wp330_saving_widgets,wp340_customize_current_theme_link,wp340_choose_image_from_library,wp350_media,wp360_revisions,wp360_locks,wp390_widgets,wp410_dfw,wp496_privacy
{PAGE_KEY}_per_page On WP_List_Table pages, how many items to display in the table. Examples of option names: edit_post_per_page, users_per_page, edit_comments_per_page, upload_per_page

User Roles and Capabilities

User Role Editor - a plugin for managing roles. WordPress user role editor, the plugin allows easy modification of user roles and capabilities.

There are 6 roles in WordPress by default:

Super Admin Super Administrator. Has rights to manage the network sites. This role appears only in multisite installation.
administrator The administrator of the site (a separate site in the network multisite).
editor Editor. Has access to all posts, pages, comments, categories, tags, and links.
author Author. Can create, upload photos, edit and publish his posts.
contributor Contributor. Can create posts, which are then published by an editor or administrator.
subscriber Subscriber. Can't do anything except edit profile.

Which role the new user gets is specified in Settings > General. The data is saved in an options: users_can_register and default_role:

List of Capabilities by Roles

A list of primitive (fundamental) user caps. These are capabilities that the specified roles (users) have by default. This list of caps is set once, when you install WordPress - it is stored in the database wp_options table in the wp_user_roles option.

Capability Super-admin Admin Editor Author Contributor Subscriber
read yes yes yes yes yes yes
delete_posts yes yes yes yes yes
edit_posts yes yes yes yes yes
delete_published_posts yes yes yes yes
edit_published_posts yes yes yes yes
publish_posts yes yes yes yes
upload_files yes yes yes yes
delete_others_pages yes yes yes
delete_others_posts yes yes yes
delete_pages yes yes yes
delete_private_pages yes yes yes
delete_private_posts yes yes yes
delete_published_pages yes yes yes
edit_others_pages yes yes yes
edit_others_posts yes yes yes
edit_pages yes yes yes
edit_private_pages yes yes yes
edit_private_posts yes yes yes
edit_published_pages yes yes yes
manage_categories yes yes yes
manage_links yes yes yes
moderate_comments yes yes yes
publish_pages yes yes yes
read_private_pages yes yes yes
read_private_posts yes yes yes
unfiltered_html yes yes ¹ yes ¹
activate_plugins yes yes ²
create_users yes yes ¹
deactivate_plugins yes yes
delete_plugins yes yes ¹
delete_themes yes yes ¹
delete_users yes yes ¹
edit_dashboard yes yes
edit_files yes yes ¹
edit_plugins yes yes ¹
edit_theme_options yes yes
edit_themes yes yes ¹
edit_users yes yes ¹
export yes yes
import yes yes
install_languages yes yes ¹
install_plugins yes yes ¹
install_themes yes yes ¹
list_users yes yes
manage_options yes yes
promote_users yes yes
remove_users yes yes
switch_themes yes yes
update_core yes yes ¹
update_languages yes yes ¹
update_plugins yes yes ¹
update_themes yes yes ¹
unfiltered_upload yes ³ yes ³
manage_network_options yes
manage_network_plugins yes
manage_network_themes yes
manage_network_users yes
manage_network yes
manage_sites yes
setup_network yes
upgrade_network yes
  • ¹ — when one site (not a multisite).
  • ² — when one site (not a multisite). Or enabled in the network settings.
  • ³ — this right must be included separately, more below.

Meta Capabilities

Above is a list of primitive (fundamental) rights. But there are also so-called meta-rights. They are not saved anywhere, but are computed "on the fly" and eventually turn into a primitive right.

List of meta-rights:

activate_plugin
activate_plugins
add_comment_meta
add_post_meta
add_term_meta
add_user_meta
add_users
assign_categories
assign_post_tags
assign_term
create_app_password
create_sites
create_users
customize
deactivate_plugin
deactivate_plugins
delete_app_password
delete_app_passwords
delete_categories
delete_comment_meta
delete_page
delete_page
delete_plugins
delete_post
delete_post
delete_post_meta
delete_post_tags
delete_site
delete_sites
delete_term
delete_term_meta
delete_themes
delete_user
delete_user
delete_user_meta
delete_users
edit_app_password
edit_categories
edit_comment
edit_comment
edit_comment_meta
edit_css
edit_files
edit_page
edit_page
edit_plugins
edit_post
edit_post
edit_post_meta
edit_post_tags
edit_term
edit_term_meta
edit_themes
edit_user
edit_user
edit_user_meta
edit_users
erase_others_personal_data
export_others_personal_data
install_languages
install_plugins
install_themes
list_app_passwords
manage_links
manage_network
manage_network_options
manage_network_plugins
manage_network_themes
manage_network_users
manage_post_tags
manage_privacy_options
manage_sites
promote_user
promote_user
publish_post
read_app_password
read_page
read_page
read_post
read_post
remove_user
remove_user
resume_plugin
resume_theme
setup_network
unfiltered_html
unfiltered_upload
update_core
update_https
update_languages
update_php
update_plugins
update_themes
upgrade_network
upload_plugins
upload_themes

edit_term                   — WP 4.7 — It does not check who created the term - it only checks if the specified term and taxonomy exist.
delete_term                 — WP 4.7 —
assign_term                 — WP 4.7 —
activate_plugin             — WP 4.9 — current_user_can( 'activate_plugin', 'my-plugin/my-plugin.php' )
deactivate_plugin           — WP 4.9 — current_user_can( 'deactivate_plugin', 'my-plugin/my-plugin.php' )

export_others_personal_data — WP 4.9.6 — is_multisite() ? 'manage_network' : 'manage_options'
erase_others_personal_data  — WP 4.9.6 — is_multisite() ? 'manage_network' : 'manage_options'
manage_privacy_options      — WP 4.9.6 — is_multisite() ? 'manage_network' : 'manage_options'

update_php                  — WP 5.0 — is_multisite() ? is_super_admin() : update_core
update_https                — WP 5.7 — is_multisite() ? is_super_admin() : manage_options | update_core

create_app_password         — WP 5.7 — map_meta_cap( 'edit_user', $user_id )
list_app_passwords          — WP 5.7 — map_meta_cap( 'edit_user', $user_id )
read_app_password           — WP 5.7 — map_meta_cap( 'edit_user', $user_id )
edit_app_password           — WP 5.7 — map_meta_cap( 'edit_user', $user_id )
delete_app_passwords        — WP 5.7 — map_meta_cap( 'edit_user', $user_id )
delete_app_password         — WP 5.7 — map_meta_cap( 'edit_user', $user_id )

To check such rights, you need to pass additional parameters, such as the ID of the post for which you want to check whether the user can edit it. For example:

if( current_user_can( 'edit_post', 123 ) ){
	 echo 'The current user can edit post 123';
}

In this case, WP checks on the fly whether the user is the author of that post, or has the primitive right to edit all posts. As a result, if the check is passed, this meta right turns into a similar primitive right edit_posts that allows the action to be performed.

Read more about meta rights in map_meta_cap().

unfiltered_upload

By default, the unfiltered_upload capability is available to the administrator. However, this right is locked by default, i.e. roles will not pass the if( current_user_can('unfiltered_upload') ) despite having this right.

To make the unfiltered_upload capability start working as expected, you need to add following constant in wp-config.php:

define( 'ALLOW_UNFILTERED_UPLOADS', true );

With the definition of this constant, roles with unfiltered_upload permission will be able to upload files with any extension (without checking the file type).

For multisite, only the Super Administrator has the unfiltered_upload right. If another role has the unfiltered_upload right, it will simply be ignored. See checking the meta-right in map_meta_cap() for details:

case 'unfiltered_upload':
	if ( defined( 'ALLOW_UNFILTERED_UPLOADS' ) && ALLOW_UNFILTERED_UPLOADS && ( ! is_multisite() || is_super_admin( $user_id ) ) ) {
		$caps[] = $cap;
	} else {
		$caps[] = 'do_not_allow';
	}
	break;

PHP Functions

See the full list of functions here. Here are some of the functions:

current_user_can() Whether the current user has a specific capability.
wp_get_current_user() Retrieve the current authorized user data (WP_User object). Sets current user, if not set yet.
get_current_user_id() Get the current user's ID.
is_user_logged_in() Checks if the current visitor is a logged in user.
get_userdata() Retrieve user data by user ID as WP_User object.
get_user_by() Gets the user by the specified field and the value of this field (by ID, login, mail).
get_users() Gets users according to the passed parameters.
update_user_meta() Update user meta field based on user ID.
get_user_meta() Gets an single meta field or all meta fields of the specified user.
delete_user_meta() Remove metadata matching criteria from a user.
map_meta_cap() Map meta capabilities to primitive capabilities.
wp_insert_user() Creates a WordPress user in the Database.
wp_update_user() Update a user data in the database. Work with both tables wp_usermeta and wp_users.
wp_create_user() A simpler way of inserting a user into the database.
register_new_user() Handles registering a new user.
wp_login_url() Retrieves the login URL.
wp_signon() Authenticates and logs a user in with 'remember' capability.
wp_set_password() Updates the user's password with a new encrypted one. Updates the specified password in the database and resets the user's cache.
wp_check_password() Checks the plaintext password against the encrypted Password.
WP_User::add_cap() Add capability and grant or deny access to capability.

User Authorization (Setting) Process

To set the current user in the core, the following functions are hooked onto the determine_current_user hook. Each of them sets the current user for different types of requests (front, REST request).

add_filter( 'determine_current_user', 'wp_validate_auth_cookie' );
add_filter( 'determine_current_user', 'wp_validate_logged_in_cookie', 20 );
add_filter( 'determine_current_user', 'wp_validate_application_password', 20 );

The hook determine_current_user is triggered upon the first call of the function wp_get_current_user(), which is based on the function _wp_get_current_user().

_wp_get_current_user() sets the current user in the global variable $current_user upon the first call and retrieves data from there on subsequent calls.

The earliest the function wp_get_current_user() can be called is the plugins_loaded event (preferably with a high priority, so it runs at the end), i.e., after all plugins are loaded and their basic initialization is completed.

In general, it is recommended to call it on the init hook, i.e., after the core and all plugins are loaded and their basic code is executed, and the next step is to display data on the screen.